-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4194 from parasharrajat/context-menu
Context-menu repositioned
- Loading branch information
Showing
11 changed files
with
720 additions
and
460 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
src/pages/home/report/ContextMenu/BaseReportActionContextMenu.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import React from 'react'; | ||
import {View} from 'react-native'; | ||
import _ from 'underscore'; | ||
import getReportActionContextMenuStyles from '../../../../styles/getReportActionContextMenuStyles'; | ||
import ContextMenuItem from '../../../../components/ContextMenuItem'; | ||
import { | ||
propTypes as GenericReportActionContextMenuPropTypes, | ||
defaultProps, | ||
} from './GenericReportActionContextMenuPropTypes'; | ||
import withLocalize, {withLocalizePropTypes} from '../../../../components/withLocalize'; | ||
import ContextMenuActions from './ContextMenuActions'; | ||
|
||
const propTypes = { | ||
...GenericReportActionContextMenuPropTypes, | ||
...withLocalizePropTypes, | ||
}; | ||
|
||
class BaseReportActionContextMenu extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
|
||
this.wrapperStyle = getReportActionContextMenuStyles(this.props.isMini); | ||
} | ||
|
||
render() { | ||
return this.props.isVisible && ( | ||
<View style={this.wrapperStyle}> | ||
{_.map(ContextMenuActions, contextAction => contextAction.shouldShow(this.props.reportAction) && ( | ||
<ContextMenuItem | ||
icon={contextAction.icon} | ||
text={this.props.translate(contextAction.textTranslateKey)} | ||
successIcon={contextAction.successIcon} | ||
successText={contextAction.successTextTranslateKey | ||
? this.props.translate(contextAction.successTextTranslateKey) | ||
: undefined} | ||
isMini={this.props.isMini} | ||
key={contextAction.textTranslateKey} | ||
onPress={() => contextAction.onPress(!this.props.isMini, { | ||
reportAction: this.props.reportAction, | ||
reportID: this.props.reportID, | ||
draftMessage: this.props.draftMessage, | ||
selection: this.props.selection, | ||
})} | ||
/> | ||
))} | ||
</View> | ||
); | ||
} | ||
} | ||
|
||
BaseReportActionContextMenu.propTypes = propTypes; | ||
BaseReportActionContextMenu.defaultProps = defaultProps; | ||
|
||
export default withLocalize(BaseReportActionContextMenu); |
116 changes: 116 additions & 0 deletions
116
src/pages/home/report/ContextMenu/ContextMenuActions.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import _ from 'underscore'; | ||
import lodashGet from 'lodash/get'; | ||
import Str from 'expensify-common/lib/str'; | ||
import { | ||
Clipboard as ClipboardIcon, LinkCopy, Mail, Pencil, Trashcan, Checkmark, | ||
} from '../../../../components/Icon/Expensicons'; | ||
import { | ||
setNewMarkerPosition, updateLastReadActionID, saveReportActionDraft, | ||
} from '../../../../libs/actions/Report'; | ||
import Clipboard from '../../../../libs/Clipboard'; | ||
import {isReportMessageAttachment, canEditReportAction, canDeleteReportAction} from '../../../../libs/reportUtils'; | ||
import ReportActionComposeFocusManager from '../../../../libs/ReportActionComposeFocusManager'; | ||
import {hideContextMenu, showDeleteModal} from './ReportActionContextMenu'; | ||
|
||
/** | ||
* Gets the HTML version of the message in an action. | ||
* @param {Object} reportAction | ||
* @return {String} | ||
*/ | ||
function getActionText(reportAction) { | ||
const message = _.last(lodashGet(reportAction, 'message', null)); | ||
return lodashGet(message, 'html', ''); | ||
} | ||
|
||
// A list of all the context actions in this menu. | ||
export default [ | ||
// Copy to clipboard | ||
{ | ||
textTranslateKey: 'contextMenuItem.copyToClipboard', | ||
icon: ClipboardIcon, | ||
successTextTranslateKey: 'contextMenuItem.copied', | ||
successIcon: Checkmark, | ||
shouldShow: () => true, | ||
|
||
// If return value is true, we switch the `text` and `icon` on | ||
// `ContextMenuItem` with `successText` and `successIcon` which will fallback to | ||
// the `text` and `icon` | ||
onPress: (closePopover, {reportAction, selection}) => { | ||
const message = _.last(lodashGet(reportAction, 'message', null)); | ||
const html = lodashGet(message, 'html', ''); | ||
const text = Str.htmlDecode(selection || lodashGet(message, 'text', '')); | ||
const isAttachment = _.has(reportAction, 'isAttachment') | ||
? reportAction.isAttachment | ||
: isReportMessageAttachment(text); | ||
if (!isAttachment) { | ||
Clipboard.setString(text); | ||
} else { | ||
Clipboard.setString(html); | ||
} | ||
if (closePopover) { | ||
hideContextMenu(true, ReportActionComposeFocusManager.focus); | ||
} | ||
}, | ||
}, | ||
|
||
{ | ||
textTranslateKey: 'reportActionContextMenu.copyLink', | ||
icon: LinkCopy, | ||
shouldShow: () => false, | ||
onPress: () => {}, | ||
}, | ||
|
||
{ | ||
textTranslateKey: 'reportActionContextMenu.markAsUnread', | ||
icon: Mail, | ||
successIcon: Checkmark, | ||
shouldShow: () => true, | ||
onPress: (closePopover, {reportAction, reportID}) => { | ||
updateLastReadActionID(reportID, reportAction.sequenceNumber); | ||
setNewMarkerPosition(reportID, reportAction.sequenceNumber); | ||
if (closePopover) { | ||
hideContextMenu(true, ReportActionComposeFocusManager.focus); | ||
} | ||
}, | ||
}, | ||
|
||
{ | ||
textTranslateKey: 'reportActionContextMenu.editComment', | ||
icon: Pencil, | ||
shouldShow: reportAction => canEditReportAction(reportAction), | ||
onPress: (closePopover, {reportID, reportAction, draftMessage}) => { | ||
const editAction = () => saveReportActionDraft( | ||
reportID, | ||
reportAction.reportActionID, | ||
_.isEmpty(draftMessage) ? getActionText(reportAction) : '', | ||
); | ||
|
||
if (closePopover) { | ||
// Hide popover, then call editAction | ||
hideContextMenu(false, editAction); | ||
return; | ||
} | ||
|
||
// No popover to hide, call editAction immediately | ||
editAction(); | ||
}, | ||
}, | ||
{ | ||
textTranslateKey: 'reportActionContextMenu.deleteComment', | ||
icon: Trashcan, | ||
shouldShow: reportAction => canDeleteReportAction(reportAction), | ||
onPress: (closePopover, {reportID, reportAction}) => { | ||
if (closePopover) { | ||
// Hide popover, then call showDeleteConfirmModal | ||
hideContextMenu( | ||
false, | ||
() => showDeleteModal(reportID, reportAction), | ||
); | ||
return; | ||
} | ||
|
||
// No popover to hide, call showDeleteConfirmModal immediately | ||
showDeleteModal(reportID, reportAction); | ||
}, | ||
}, | ||
]; |
32 changes: 32 additions & 0 deletions
32
src/pages/home/report/ContextMenu/GenericReportActionContextMenuPropTypes.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import PropTypes from 'prop-types'; | ||
import ReportActionPropTypes from '../ReportActionPropTypes'; | ||
|
||
const propTypes = { | ||
/** The ID of the report this report action is attached to. */ | ||
reportID: PropTypes.number.isRequired, | ||
|
||
/** The report action this context menu is attached to. */ | ||
reportAction: PropTypes.shape(ReportActionPropTypes).isRequired, | ||
|
||
/** If true, this component will be a small, row-oriented menu that displays icons but not text. | ||
If false, this component will be a larger, column-oriented menu that displays icons alongside text in each row. */ | ||
isMini: PropTypes.bool, | ||
|
||
/** Controls the visibility of this component. */ | ||
isVisible: PropTypes.bool, | ||
|
||
/** The copy selection of text. */ | ||
selection: PropTypes.string, | ||
|
||
/** Draft message - if this is set the comment is in 'edit' mode */ | ||
draftMessage: PropTypes.string, | ||
}; | ||
|
||
const defaultProps = { | ||
isMini: false, | ||
isVisible: false, | ||
selection: '', | ||
draftMessage: '', | ||
}; | ||
|
||
export {propTypes, defaultProps}; |
36 changes: 36 additions & 0 deletions
36
src/pages/home/report/ContextMenu/MiniReportActionContextMenu/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import _ from 'underscore'; | ||
import React from 'react'; | ||
import {View} from 'react-native'; | ||
import PropTypes from 'prop-types'; | ||
import { | ||
propTypes as GenericReportActionContextMenuPropTypes, | ||
defaultProps as GenericReportActionContextMenuDefaultProps, | ||
} from '../GenericReportActionContextMenuPropTypes'; | ||
import {getMiniReportActionContextMenuWrapperStyle} from '../../../../../styles/getReportActionItemStyles'; | ||
import BaseReportActionContextMenu from '../BaseReportActionContextMenu'; | ||
|
||
const propTypes = { | ||
..._.omit(GenericReportActionContextMenuPropTypes, ['isMini']), | ||
|
||
/** Should the reportAction this menu is attached to have the appearance of being | ||
* grouped with the previous reportAction? */ | ||
displayAsGroup: PropTypes.bool, | ||
}; | ||
|
||
const defaultProps = { | ||
..._.omit(GenericReportActionContextMenuDefaultProps, ['isMini']), | ||
displayAsGroup: false, | ||
}; | ||
|
||
const MiniReportActionContextMenu = props => ( | ||
<View style={getMiniReportActionContextMenuWrapperStyle(props.displayAsGroup)}> | ||
{/* eslint-disable-next-line react/jsx-props-no-spreading */} | ||
<BaseReportActionContextMenu isMini {...props} /> | ||
</View> | ||
); | ||
|
||
MiniReportActionContextMenu.propTypes = propTypes; | ||
MiniReportActionContextMenu.defaultProps = defaultProps; | ||
MiniReportActionContextMenu.displayName = 'MiniReportActionContextMenu'; | ||
|
||
export default MiniReportActionContextMenu; |
1 change: 1 addition & 0 deletions
1
src/pages/home/report/ContextMenu/MiniReportActionContextMenu/index.native.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export default () => null; |
Oops, something went wrong.