diff --git a/src/components/UnreadActionIndicator.js b/src/components/UnreadActionIndicator.js
index 0a3fa8d3d95d..d2ffcc232c2a 100644
--- a/src/components/UnreadActionIndicator.js
+++ b/src/components/UnreadActionIndicator.js
@@ -1,29 +1,17 @@
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 c40efa8d516d..0a6863134d11 100644
--- a/src/pages/home/report/ReportActionItem.js
+++ b/src/pages/home/report/ReportActionItem.js
@@ -16,6 +16,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.
@@ -27,6 +28,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?
+ displayNewIndicator: PropTypes.bool.isRequired,
+
/* --- Onyx Props --- */
// List of betas for the current user.
betas: PropTypes.arrayOf(PropTypes.string),
@@ -58,6 +62,7 @@ class ReportActionItem extends Component {
shouldComponentUpdate(nextProps, nextState) {
return this.state.isPopoverVisible !== nextState.isPopoverVisible
|| this.props.displayAsGroup !== nextProps.displayAsGroup
+ || (this.props.displayNewIndicator !== nextProps.displayNewIndicator)
|| !_.isEqual(this.props.action, nextProps.action);
}
@@ -109,6 +114,7 @@ class ReportActionItem extends Component {
{hovered => (
+ {this.props.displayNewIndicator && }
{!this.props.displayAsGroup
?
diff --git a/src/pages/home/report/ReportActionsView.js b/src/pages/home/report/ReportActionsView.js
index 708130ac689f..8daefa4808fe 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,
@@ -69,16 +67,10 @@ class ReportActionsView extends React.Component {
this.recordMaxAction = this.recordMaxAction.bind(this);
this.onVisibilityChange = this.onVisibilityChange.bind(this);
this.loadMoreChats = this.loadMoreChats.bind(this);
+ this.scheduledRecordMaxAction = this.scheduledRecordMaxAction.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;
-
- // Helper variable that prevents the unread indicator to show up for new messages
- // received while the report is still active
- this.shouldShowUnreadActionIndicator = true;
+ this.unreadTimer = null;
+ this.newMessageMarkerPosition = -1;
this.state = {
isLoadingMoreChats: false,
@@ -127,10 +119,9 @@ class ReportActionsView extends React.Component {
this.scrollToListBottom();
}
- // When the last action changes, wait three seconds, then record the max action
- // This will make the unread indicator go away if you receive comments in the same chat you're looking at
- if (Visibility.isVisible()) {
- this.timers.push(setTimeout(this.recordMaxAction, 3000));
+ // If we are adding a new action while the chat is open, record the max action immediately
+ if (!this.unreadTimer && Visibility.isVisible()) {
+ this.scheduledRecordMaxAction();
}
}
}
@@ -142,7 +133,10 @@ class ReportActionsView extends React.Component {
AppState.removeEventListener('change', this.onVisibilityChange);
- _.each(this.timers, timer => clearTimeout(timer));
+ if (this.unreadTimer) {
+ clearTimeout(this.unreadTimer);
+ this.unreadTimer = null;
+ }
unsubscribeFromReportChannel(this.props.reportID);
}
@@ -151,33 +145,21 @@ class ReportActionsView extends React.Component {
*/
onVisibilityChange() {
if (Visibility.isVisible()) {
- this.timers.push(setTimeout(this.recordMaxAction, 3000));
+ this.unreadTimer = setTimeout(this.scheduledRecordMaxAction, 3000);
}
}
/**
- * 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
+ * Sets the max action after a set delay
*/
- setUpUnreadActionIndicator() {
- if (!this.shouldShowUnreadActionIndicator) {
- return;
- }
-
- 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));
+ scheduledRecordMaxAction() {
+ // Always cancel the existing timer
+ if (this.unreadTimer) {
+ clearTimeout(this.unreadTimer);
+ this.unreadTimer = null;
}
- this.shouldShowUnreadActionIndicator = false;
+ this.recordMaxAction();
}
/**
@@ -192,6 +174,12 @@ class ReportActionsView extends React.Component {
// Fetch the new set of actions
fetchActions(this.props.reportID);
+ this.newMessageMarkerPosition = -1;
+
+ // Wait three seconds, then record the max action
+ if (Visibility.isVisible()) {
+ this.unreadTimer = setTimeout(this.scheduledRecordMaxAction, 3000);
+ }
}
/**
@@ -335,15 +323,14 @@ class ReportActionsView extends React.Component {
// 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.newMessageMarkerPosition}
/>
);
@@ -364,7 +351,12 @@ class ReportActionsView extends React.Component {
);
}
- this.setUpUnreadActionIndicator();
+ if (this.newMessageMarkerPosition < 0) {
+ this.newMessageMarkerPosition = this.props.report.unreadActionCount === 0
+ ? this.props.report.unreadActionCount
+ : _.size(this.props.reportActions) - this.props.report.unreadActionCount;
+ }
+
this.updateSortedReportActions();
return (