diff --git a/src/components/UnreadActionIndicator.js b/src/components/UnreadActionIndicator.js index 0a3fa8d3d95d..7c6789c0a66a 100644 --- a/src/components/UnreadActionIndicator.js +++ b/src/components/UnreadActionIndicator.js @@ -1,29 +1,16 @@ import React from 'react'; -import {Animated, View} from 'react-native'; -import PropTypes from 'prop-types'; -import styles, {getOpacityStyle} from '../styles/styles'; +import {View} from 'react-native'; +import styles from '../styles/styles'; import Text from './Text'; -const propTypes = { - // Animated opacity - // eslint-disable-next-line react/forbid-prop-types - animatedOpacity: PropTypes.object.isRequired, -}; - -const UnreadActionIndicator = props => ( - +const UnreadActionIndicator = () => ( + NEW - + ); -UnreadActionIndicator.propTypes = propTypes; UnreadActionIndicator.displayName = 'UnreadActionIndicator'; - export default UnreadActionIndicator; diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 060f99c8770a..7d0608ce4aa2 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -13,6 +13,7 @@ import PopoverWithMeasuredContent from '../../../components/PopoverWithMeasuredC import ReportActionItemSingle from './ReportActionItemSingle'; import ReportActionItemGrouped from './ReportActionItemGrouped'; import ReportActionContextMenu from './ReportActionContextMenu'; +import UnreadActionIndicator from '../../../components/UnreadActionIndicator'; const propTypes = { // The ID of the report this action is on. @@ -23,6 +24,9 @@ const propTypes = { // Should the comment have the appearance of being grouped with the previous comment? displayAsGroup: PropTypes.bool.isRequired, + + // Should we display the new indicator on top of the comment? + shouldDisplayNewIndicator: PropTypes.bool.isRequired, }; class ReportActionItem extends Component { @@ -46,6 +50,7 @@ class ReportActionItem extends Component { shouldComponentUpdate(nextProps, nextState) { return this.state.isPopoverVisible !== nextState.isPopoverVisible || this.props.displayAsGroup !== nextProps.displayAsGroup + || (this.props.shouldDisplayNewIndicator !== nextProps.shouldDisplayNewIndicator) || !_.isEqual(this.props.action, nextProps.action); } @@ -85,6 +90,9 @@ class ReportActionItem extends Component { {hovered => ( + {!hovered && this.props.shouldDisplayNewIndicator && ( + + )} {!this.props.displayAsGroup ? diff --git a/src/pages/home/report/ReportActionsView.js b/src/pages/home/report/ReportActionsView.js index d41e7a3c0d86..347dd3d5ee48 100644 --- a/src/pages/home/report/ReportActionsView.js +++ b/src/pages/home/report/ReportActionsView.js @@ -1,6 +1,5 @@ import React from 'react'; import { - Animated, View, Keyboard, AppState, @@ -11,7 +10,6 @@ import _ from 'underscore'; import lodashGet from 'lodash/get'; import {withOnyx} from 'react-native-onyx'; import Text from '../../../components/Text'; -import UnreadActionIndicator from '../../../components/UnreadActionIndicator'; import { fetchActions, updateLastReadActionID, @@ -39,6 +37,9 @@ const propTypes = { report: PropTypes.shape({ // Number of actions unread unreadActionCount: PropTypes.number, + + // The largest sequenceNumber on this report + maxSequenceNumber: PropTypes.number, }), // Array of report actions for this report @@ -54,6 +55,7 @@ const propTypes = { const defaultProps = { report: { unreadActionCount: 0, + maxSequenceNumber: 0, }, reportActions: {}, session: {}, @@ -71,10 +73,10 @@ class ReportActionsView extends React.Component { this.loadMoreChats = this.loadMoreChats.bind(this); this.sortedReportActions = []; this.timers = []; - this.unreadIndicatorOpacity = new Animated.Value(1); - // Helper variable that keeps track of the unread action count before it updates to zero - this.unreadActionCount = 0; + this.initialNewMarkerPosition = props.report.unreadActionCount === 0 + ? 0 + : (props.report.maxSequenceNumber + 1) - props.report.unreadActionCount; this.state = { isLoadingMoreChats: false, @@ -89,7 +91,6 @@ class ReportActionsView extends React.Component { this.keyboardEvent = Keyboard.addListener('keyboardDidShow', this.scrollToListBottom); this.recordMaxAction(); fetchActions(this.props.reportID); - this.setUpUnreadActionIndicator(); Timing.end(CONST.TIMING.SWITCH_REPORT, CONST.TIMING.COLD); } @@ -146,25 +147,6 @@ class ReportActionsView extends React.Component { } } - /** - * Checks if the unreadActionIndicator should be shown. - * If it does, starts a timeout for the fading out animation and creates - * a flag to not show it again if the report is still open - */ - setUpUnreadActionIndicator() { - this.unreadActionCount = this.props.report.unreadActionCount; - - if (this.unreadActionCount > 0) { - this.unreadIndicatorOpacity = new Animated.Value(1); - this.timers.push(setTimeout(() => { - Animated.timing(this.unreadIndicatorOpacity, { - toValue: 0, - useNativeDriver: false, - }).start(); - }, 3000)); - } - } - /** * Retrieves the next set of report actions for the chat once we are nearing the end of what we are currently * displaying. @@ -232,8 +214,7 @@ class ReportActionsView extends React.Component { } /** - * When the bottom of the list is reached, this is triggered, so it's a little different than recording the max - * action when scrolled + * Recorded when the report first opens and when the list is scrolled to the bottom */ recordMaxAction() { const reportActions = lodashGet(this.props, 'reportActions', {}); @@ -265,8 +246,8 @@ class ReportActionsView extends React.Component { /** * This function overrides the CellRendererComponent (defaults to a plain View), giving each ReportActionItem a - * higher z-index than the one below it. This prevents issues where the ReportActionContextMenu overlapping between - * rows is hidden beneath other rows. + * higher z-index than the one below it. This prevents issues where the ReportActionContextMenu overlapping between + * rows is hidden beneath other rows. * * @param {Object} index - The ReportAction item in the FlatList. * @param {Object|Array} style – The default styles of the CellRendererComponent provided by the CellRenderer. @@ -291,31 +272,21 @@ class ReportActionsView extends React.Component { * @param {Object} args * @param {Object} args.item * @param {Number} args.index - * @param {Function} args.onLayout * * @returns {React.Component} */ renderItem({ item, index, - onLayout, }) { return ( - - // Using instead of a Fragment because there is a difference between how - // are implemented on native and web/desktop which leads to - // the unread indicator on native to render below the message instead of above it. - - {this.unreadActionCount > 0 && index === this.unreadActionCount - 1 && ( - - )} - - + 0 + && item.action.sequenceNumber === this.initialNewMarkerPosition} + /> ); } @@ -334,7 +305,6 @@ class ReportActionsView extends React.Component { ); } - this.setUpUnreadActionIndicator(); return ( this.actionListElement = el} diff --git a/src/styles/getReportActionItemStyles.js b/src/styles/getReportActionItemStyles.js index 20054eb0eef0..7923c085b536 100644 --- a/src/styles/getReportActionItemStyles.js +++ b/src/styles/getReportActionItemStyles.js @@ -1,3 +1,4 @@ +import colors from './colors'; import themeColors from './themes/default'; import positioning from './utilities/positioning'; @@ -11,7 +12,11 @@ export function getReportActionItemStyle(isHovered = false) { return { display: 'flex', justifyContent: 'space-between', - backgroundColor: isHovered ? themeColors.hoverComponentBG : themeColors.componentBG, + backgroundColor: isHovered + ? themeColors.hoverComponentBG + + // Warning: Setting this to a non-transparent color will cause unread indicator to break on Android + : colors.transparent, cursor: 'default', }; } diff --git a/src/styles/styles.js b/src/styles/styles.js index 0ea54b06c18b..f50e34339a47 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -828,14 +828,6 @@ const styles = { marginRight: 4, }, - navigationMenuOpenAbsolute: { - position: 'absolute', - left: 0, - top: 0, - bottom: 0, - zIndex: 2, - }, - navigationModalOverlay: { position: 'absolute', width: '100%', @@ -1151,6 +1143,7 @@ const styles = { paddingHorizontal: 20, flexDirection: 'row', alignItems: 'center', + zIndex: 1, }, unreadIndicatorLine: { @@ -1518,14 +1511,6 @@ function getWidthAndHeightStyle(width, height) { }; } -/** - * @param {Number} opacity - * @returns {Object} - */ -function getOpacityStyle(opacity) { - return {opacity}; -} - /** * @param {Object} params * @returns {Object} @@ -1564,6 +1549,5 @@ export { getIconFillColor, getAnimatedFABStyle, getWidthAndHeightStyle, - getOpacityStyle, getModalPaddingStyles, };