Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import {Pressable} from 'react-native';
import * as anchorForAttachmentsOnlyPropTypes from './anchorForAttachmentsOnlyPropTypes';
import AttachmentView from '../AttachmentView';
import fileDownload from '../../libs/fileDownload';
import addEncryptedAuthTokenToURL from '../../libs/addEncryptedAuthTokenToURL';

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

this.state = {
isDownloading: false,
};
this.processDownload = this.processDownload.bind(this);
}

/**
* Initiate file downloading and update downloading flags
*
* @param {String} href
* @param {String} fileName
*/
processDownload(href, fileName) {
this.setState({isDownloading: true});
fileDownload(href, fileName).then(() => this.setState({isDownloading: false}));
}

render() {
const source = addEncryptedAuthTokenToURL(this.props.source);
Copy link
Copy Markdown
Contributor

@hungvu193 hungvu193 Jan 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't add encyptToken for local file, it will cause error console.
More details: #54640

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hungvu193 Seriously. This PR is 3 years old. At that time w me didn't have local file. Also, this PR only does refactoring.

Can you please find a proper PR which surfaced the issue?

Copy link
Copy Markdown
Contributor

@hungvu193 hungvu193 Jan 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're correct. My bad, just found the offending PR.


return (
<Pressable
style={this.props.style}
onPress={() => {
if (this.state.isDownloading) {
return;
}
this.processDownload(source, this.props.displayName);
}}
>
<AttachmentView
sourceURL={source}
file={{name: this.props.displayName}}
shouldShowDownloadIcon
shouldShowLoadingSpinnerIcon={this.state.isDownloading}
/>
</Pressable>
);
}
}

BaseAnchorForAttachmentsOnly.propTypes = anchorForAttachmentsOnlyPropTypes.propTypes;
BaseAnchorForAttachmentsOnly.defaultProps = anchorForAttachmentsOnlyPropTypes.defaultProps;

export default BaseAnchorForAttachmentsOnly;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import PropTypes from 'prop-types';
import stylePropTypes from '../../styles/stylePropTypes';

const propTypes = {
/** The URL of the attachment */
source: PropTypes.string,

/** Filename for attachments. */
displayName: PropTypes.string,

/** Any additional styles to apply */
style: stylePropTypes,
};

const defaultProps = {
source: '',
style: {},
displayName: '',
};

export {propTypes, defaultProps};
12 changes: 12 additions & 0 deletions src/components/AnchorForAttachmentsOnly/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import * as anchorForAttachmentsOnlyPropTypes from './anchorForAttachmentsOnlyPropTypes';
import BaseAnchorForAttachmentsOnly from './BaseAnchorForAttachmentsOnly';

// eslint-disable-next-line react/jsx-props-no-spreading
const AnchorForAttachmentsOnly = props => <BaseAnchorForAttachmentsOnly {...props} />;

AnchorForAttachmentsOnly.propTypes = anchorForAttachmentsOnlyPropTypes.propTypes;
AnchorForAttachmentsOnly.defaultProps = anchorForAttachmentsOnlyPropTypes.defaultProps;
AnchorForAttachmentsOnly.displayName = 'AnchorForAttachmentsOnly';

export default AnchorForAttachmentsOnly;
13 changes: 13 additions & 0 deletions src/components/AnchorForAttachmentsOnly/index.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import * as anchorForAttachmentsOnlyPropTypes from './anchorForAttachmentsOnlyPropTypes';
import BaseAnchorForAttachmentsOnly from './BaseAnchorForAttachmentsOnly';
import styles from '../../styles/styles';

// eslint-disable-next-line react/jsx-props-no-spreading
const AnchorForAttachmentsOnly = props => <BaseAnchorForAttachmentsOnly {...props} style={styles.mw100} />;

AnchorForAttachmentsOnly.propTypes = anchorForAttachmentsOnlyPropTypes.propTypes;
AnchorForAttachmentsOnly.defaultProps = anchorForAttachmentsOnlyPropTypes.defaultProps;
AnchorForAttachmentsOnly.displayName = 'AnchorForAttachmentsOnly';

export default AnchorForAttachmentsOnly;
107 changes: 107 additions & 0 deletions src/components/AnchorForCommentsOnly.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import _ from 'underscore';
import React from 'react';
import {StyleSheet} from 'react-native';
import lodashGet from 'lodash/get';
import Str from 'expensify-common/lib/str';
import PropTypes from 'prop-types';
import Text from './Text';
import PressableWithSecondaryInteraction from './PressableWithSecondaryInteraction';
import * as ReportActionContextMenu from '../pages/home/report/ContextMenu/ReportActionContextMenu';
import * as ContextMenuActions from '../pages/home/report/ContextMenu/ContextMenuActions';
import Tooltip from './Tooltip';
import canUseTouchScreen from '../libs/canUseTouchscreen';
import styles from '../styles/styles';
import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions';

const propTypes = {
/** The URL to open */
href: PropTypes.string,

/** What headers to send to the linked page (usually noopener and noreferrer)
This is unused in native, but is here for parity with web */
rel: PropTypes.string,

/** Used to determine where to open a link ("_blank" is passed for a new tab)
This is unused in native, but is here for parity with web */
target: PropTypes.string,

/** Any children to display */
children: PropTypes.node,

/** Anchor text of URLs or emails. */
displayName: PropTypes.string,

/** Any additional styles to apply */
// eslint-disable-next-line react/forbid-prop-types
style: PropTypes.any,

/** Press handler for the link, when not passed, default href is used to create a link like behaviour */
onPress: PropTypes.func,

...windowDimensionsPropTypes,
};

const defaultProps = {
href: '',
rel: '',
target: '',
children: null,
style: {},
displayName: '',
onPress: undefined,
};

/*
* This is a default anchor component for regular links.
*/
const BaseAnchorForCommentsOnly = (props) => {
let linkRef;
const rest = _.omit(props, _.keys(propTypes));
const linkProps = {};
if (_.isFunction(props.onPress)) {
linkProps.onPress = props.onPress;
} else {
linkProps.href = props.href;
}
const defaultTextStyle = canUseTouchScreen() || props.isSmallScreenWidth ? {} : styles.userSelectText;

return (
<PressableWithSecondaryInteraction
inline
onSecondaryInteraction={
(event) => {
ReportActionContextMenu.showContextMenu(
Str.isValidEmail(props.displayName) ? ContextMenuActions.CONTEXT_MENU_TYPES.EMAIL : ContextMenuActions.CONTEXT_MENU_TYPES.LINK,
event,
props.href,
lodashGet(linkRef, 'current'),
);
}
}
>
<Tooltip text={Str.isValidEmail(props.displayName) ? '' : props.href}>
<Text
ref={el => linkRef = el}
style={StyleSheet.flatten([props.style, defaultTextStyle])}
accessibilityRole="link"
hrefAttrs={{
rel: props.rel,
target: props.target,
}}
// eslint-disable-next-line react/jsx-props-no-spreading
{...linkProps}
// eslint-disable-next-line react/jsx-props-no-spreading
{...rest}
>
{props.children}
</Text>
</Tooltip>
</PressableWithSecondaryInteraction>
);
};

BaseAnchorForCommentsOnly.propTypes = propTypes;
BaseAnchorForCommentsOnly.defaultProps = defaultProps;
BaseAnchorForCommentsOnly.displayName = 'BaseAnchorForCommentsOnly';

export default withWindowDimensions(BaseAnchorForCommentsOnly);

This file was deleted.

Loading