Skip to content

Commit

Permalink
Refactor solution to use Pressable in AttachmentView
Browse files Browse the repository at this point in the history
  • Loading branch information
alexxxwork committed Apr 21, 2023
1 parent c9013d0 commit 439c667
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 62 deletions.
35 changes: 5 additions & 30 deletions src/components/AttachmentCarousel/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import {View, FlatList, PanResponder} from 'react-native';
import {View, FlatList, Pressable} from 'react-native';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
Expand Down Expand Up @@ -58,7 +58,7 @@ class AttachmentCarousel extends React.Component {
this.updatePage = this.updatePage.bind(this);
this.updateZoomState = this.updateZoomState.bind(this);

// Debounce arrow toggle to prevent multiply action on double-click and prevent toggle on swipe
// Debounce arrow toggle to prevent multiply action on double-click
this.toggleArrowsDebounced = _.debounce(this.toggleArrowsDebounced.bind(this), 300);

this.state = {
Expand All @@ -68,15 +68,6 @@ class AttachmentCarousel extends React.Component {
containerWidth: 0,
isZoomed: false,
};

this.panResponder = PanResponder.create({
onStartShouldSetPanResponder: (event, gestureState) => {
if (gestureState.numberActiveTouches > 1 || this.state.isZoomed) {
return false;
}
this.toggleArrowsDebounced();
},
});
}

componentDidMount() {
Expand Down Expand Up @@ -238,22 +229,8 @@ class AttachmentCarousel extends React.Component {
renderCell(props) {
const style = [props.style, styles.h100, {width: this.state.containerWidth}];

// Touch screen devices can toggle between showing and hiding the arrows by tapping on the image/container
// Other devices toggle the arrows through hovering (mouse) instead (see render() root element)
if (!this.canUseTouchScreen) {
// eslint-disable-next-line react/jsx-props-no-spreading
return <View {...props} style={style} />;
}

return (
<View
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
// eslint-disable-next-line react/jsx-props-no-spreading
{...this.panResponder.panHandlers}
style={style}
/>
);
// eslint-disable-next-line react/jsx-props-no-spreading
return <View {...props} style={style} />;
}

/**
Expand All @@ -272,6 +249,7 @@ class AttachmentCarousel extends React.Component {
source={authSource}
file={item.file}
onScaleChanged={this.updateZoomState}
onPress={this.toggleArrowsDebounced}
/>
);
}
Expand Down Expand Up @@ -357,9 +335,6 @@ class AttachmentCarousel extends React.Component {
keyExtractor={item => item.source}
viewabilityConfig={this.viewabilityConfig}
onViewableItemsChanged={this.updatePage}

// Cancel pending arrow toggle action on swipe gesture
onScroll={this.toggleArrowsDebounced.cancel}
/>
)}

Expand Down
78 changes: 46 additions & 32 deletions src/components/AttachmentView.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, {memo} from 'react';
import {View, ActivityIndicator} from 'react-native';
import React, {memo, useState} from 'react';
import {View, ActivityIndicator, Pressable} from 'react-native';
import _ from 'underscore';
import PropTypes from 'prop-types';
import Str from 'expensify-common/lib/str';
Expand Down Expand Up @@ -59,10 +59,17 @@ const defaultProps = {
};

const AttachmentView = (props) => {
const [loadComplete, setLoadComplete] = useState(false);
const containerStyles = props.isSmallScreenWidth
? [styles.w100, styles.flex1]
: [styles.alignItemsCenter, styles.flex1];

// Handles case where source is a component (ex: SVG)
if (_.isFunction(props.source)) {
return (
<Icon src={props.source} height={variables.defaultAvatarPreviewSize} width={variables.defaultAvatarPreviewSize} />
<Pressable onPress={props.onPress} style={containerStyles}>
<Icon src={props.source} height={variables.defaultAvatarPreviewSize} width={variables.defaultAvatarPreviewSize} />
</Pressable>
);
}

Expand All @@ -74,50 +81,57 @@ const AttachmentView = (props) => {
? addEncryptedAuthTokenToURL(props.source)
: props.source;
return (
<PDFView
onPress={props.onPress}
sourceURL={sourceURL}
style={styles.imageModalPDF}
onToggleKeyboard={props.onToggleKeyboard}
onScaleChanged={props.onScaleChanged}
/>
<Pressable onPress={props.onPress} disabled={loadComplete} style={containerStyles}>
<PDFView
onPress={props.onPress}
sourceURL={sourceURL}
style={styles.imageModalPDF}
onToggleKeyboard={props.onToggleKeyboard}
onScaleChanged={props.onScaleChanged}
onLoadComplete={() => !loadComplete && setLoadComplete(true)}
/>
</Pressable>
);
}

// For this check we use both source and file.name since temporary file source is a blob
// both PDFs and images will appear as images when pasted into the the text field
if (Str.isImage(props.source) || (props.file && Str.isImage(props.file.name))) {
return (
<ImageView onPress={props.onPress} url={props.source} isAuthTokenRequired={props.isAuthTokenRequired} />
<Pressable onPress={props.onPress} style={containerStyles}>
<ImageView url={props.source} isAuthTokenRequired={props.isAuthTokenRequired} />
</Pressable>
);
}

return (
<View
style={styles.defaultAttachmentView}
>
<View style={styles.mr2}>
<Icon src={Expensicons.Paperclip} />
</View>

<Text style={[styles.textStrong, styles.flexShrink1, styles.breakAll, styles.flexWrap, styles.mw100]}>{props.file && props.file.name}</Text>
{!props.shouldShowLoadingSpinnerIcon && props.shouldShowDownloadIcon && (
<View style={styles.ml2}>
<Tooltip text={props.translate('common.download')}>
<Icon src={Expensicons.Download} />
</Tooltip>
</View>
)}
{props.shouldShowLoadingSpinnerIcon && (
<View style={styles.ml2}>
<Tooltip text={props.translate('common.downloading')}>
<ActivityIndicator
size="small"
color={themeColors.textSupporting}
/>
</Tooltip>
<Pressable onPress={this.props.onPress}>
<View style={styles.mr2}>
<Icon src={Expensicons.Paperclip} />
</View>
)}

<Text style={[styles.textStrong, styles.flexShrink1, styles.breakAll, styles.flexWrap, styles.mw100]}>{props.file && props.file.name}</Text>
{!props.shouldShowLoadingSpinnerIcon && props.shouldShowDownloadIcon && (
<View style={styles.ml2}>
<Tooltip text={props.translate('common.download')}>
<Icon src={Expensicons.Download} />
</Tooltip>
</View>
)}
{props.shouldShowLoadingSpinnerIcon && (
<View style={styles.ml2}>
<Tooltip text={props.translate('common.downloading')}>
<ActivityIndicator
size="small"
color={themeColors.textSupporting}
/>
</Tooltip>
</View>
)}
</Pressable>
</View>
);
};
Expand Down
2 changes: 2 additions & 0 deletions src/components/PDFView/index.native.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, {Component} from 'react';
import {View} from 'react-native';
import PDF from 'react-native-pdf';
import _ from 'underscore';
import KeyboardAvoidingView from '../KeyboardAvoidingView';
import styles from '../../styles/styles';
import * as StyleUtils from '../../styles/StyleUtils';
Expand Down Expand Up @@ -117,6 +118,7 @@ class PDFView extends Component {
shouldRequestPassword: false,
shouldShowLoadingIndicator: false,
});
this.props.onLoadComplete();
}

render() {
Expand Down
4 changes: 4 additions & 0 deletions src/components/PDFView/pdfViewPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ const propTypes = {
/** Handles scale changed event in PDF component */
onScaleChanged: PropTypes.func,

/** Handles load complete event in PDF component */
onLoadComplete: PropTypes.func,

...windowDimensionsPropTypes,
};

Expand All @@ -27,6 +30,7 @@ const defaultProps = {
onPress: () => {},
onToggleKeyboard: () => {},
onScaleChanged: () => {},
onLoadComplete: () => {},
};

export {propTypes, defaultProps};

0 comments on commit 439c667

Please sign in to comment.