diff --git a/assets/images/avatars/deleted-room.svg b/assets/images/avatars/deleted-room.svg
new file mode 100644
index 0000000000000..cfce5daab4404
--- /dev/null
+++ b/assets/images/avatars/deleted-room.svg
@@ -0,0 +1,13 @@
+
+
+
diff --git a/src/components/Avatar.js b/src/components/Avatar.js
index 841900b2b1dd2..c3e64dbac2b2a 100644
--- a/src/components/Avatar.js
+++ b/src/components/Avatar.js
@@ -1,8 +1,8 @@
import React, {PureComponent} from 'react';
-import {Image, View, StyleSheet} from 'react-native';
+import {Image, View} from 'react-native';
import PropTypes from 'prop-types';
import styles from '../styles/styles';
-import RoomAvatar from '../../assets/images/avatars/room.svg';
+import RoomAvatar from './RoomAvatar';
const propTypes = {
/** Url source for the avatar */
@@ -19,6 +19,9 @@ const propTypes = {
/** Whether this avatar is for a default room */
isDefaultChatRoom: PropTypes.bool,
+
+ /** Whether this avatar is for an archived default room */
+ isArchivedRoom: PropTypes.bool,
};
const defaultProps = {
@@ -27,6 +30,7 @@ const defaultProps = {
containerStyles: [],
size: 'default',
isDefaultChatRoom: false,
+ isArchivedRoom: false,
};
class Avatar extends PureComponent {
@@ -42,7 +46,7 @@ class Avatar extends PureComponent {
return (
{this.props.isDefaultChatRoom
- ?
+ ?
: }
);
diff --git a/src/components/MultipleAvatars.js b/src/components/MultipleAvatars.js
index 079ac370928b4..518cf507a641a 100644
--- a/src/components/MultipleAvatars.js
+++ b/src/components/MultipleAvatars.js
@@ -18,6 +18,9 @@ const propTypes = {
/** Whether this avatar is for a default room */
isDefaultChatRoom: PropTypes.bool,
+
+ /** Whether this avatar is for an archived room */
+ isArchivedRoom: PropTypes.bool,
};
const defaultProps = {
@@ -25,10 +28,11 @@ const defaultProps = {
size: 'default',
secondAvatarStyle: [styles.secondAvatarHovered],
isDefaultChatRoom: false,
+ isArchivedRoom: false,
};
const MultipleAvatars = ({
- avatarImageURLs, size, secondAvatarStyle, isDefaultChatRoom,
+ avatarImageURLs, size, secondAvatarStyle, isDefaultChatRoom, isArchivedRoom,
}) => {
const avatarContainerStyles = size === 'small' ? styles.emptyAvatarSmall : styles.emptyAvatar;
const singleAvatarStyles = size === 'small' ? styles.singleAvatarSmall : styles.singleAvatar;
@@ -44,7 +48,12 @@ const MultipleAvatars = ({
if (avatarImageURLs.length === 1) {
return (
-
+
);
}
diff --git a/src/components/RoomAvatar.js b/src/components/RoomAvatar.js
new file mode 100644
index 0000000000000..f9675418e542f
--- /dev/null
+++ b/src/components/RoomAvatar.js
@@ -0,0 +1,31 @@
+import React, {PureComponent} from 'react';
+import {StyleSheet} from 'react-native';
+import PropTypes from 'prop-types';
+import ActiveRoomAvatar from '../../assets/images/avatars/room.svg';
+import DeletedRoomAvatar from '../../assets/images/avatars/deleted-room.svg';
+
+const propTypes = {
+ /** Extra styles to pass to Image */
+ avatarStyle: PropTypes.arrayOf(PropTypes.object),
+
+ /** Whether the room this avatar is for is deleted or not */
+ isArchived: PropTypes.bool,
+};
+
+const defaultProps = {
+ avatarStyle: [],
+ isArchived: false,
+};
+
+class RoomAvatar extends PureComponent {
+ render() {
+ return (this.props.isArchived
+ ?
+ :
+ );
+ }
+}
+
+RoomAvatar.defaultProps = defaultProps;
+RoomAvatar.propTypes = propTypes;
+export default RoomAvatar;
diff --git a/src/languages/en.js b/src/languages/en.js
index 2c13b708c4045..12e18aecbb5c9 100755
--- a/src/languages/en.js
+++ b/src/languages/en.js
@@ -30,6 +30,7 @@ export default {
privacy: 'Privacy',
privacyPolicy: 'Privacy Policy',
delete: 'Delete',
+ deleted: 'deleted',
contacts: 'Contacts',
recents: 'Recents',
close: 'Close',
@@ -107,6 +108,7 @@ export default {
blockedFromConcierge: 'Communication is barred',
youAppearToBeOffline: 'You appear to be offline.',
fileUploadFailed: 'Upload Failed. File is not supported.',
+ roomIsArchived: 'This chat room has been deleted',
},
contextMenuItem: {
copyToClipboard: 'Copy to Clipboard',
diff --git a/src/languages/es.js b/src/languages/es.js
index de5b415a1fdf3..6290af5dd0af9 100644
--- a/src/languages/es.js
+++ b/src/languages/es.js
@@ -26,6 +26,7 @@ export default {
and: 'y',
details: 'Detalles',
delete: 'Eliminar',
+ deleted: 'eliminado',
contacts: 'Contactos',
recents: 'Recientes',
close: 'Cerrar',
@@ -102,6 +103,7 @@ export default {
writeSomething: 'Escribe algo...',
blockedFromConcierge: 'Comunicación no permitida',
youAppearToBeOffline: 'Parece que estás desconectado.',
+ roomIsArchived: 'Esta sala de chat ha sido eliminada',
},
reportActionContextMenu: {
copyToClipboard: 'Copiar al Portapapeles',
diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js
index 56a2eaa54e9d1..a59adb074c058 100644
--- a/src/libs/OptionsListUtils.js
+++ b/src/libs/OptionsListUtils.js
@@ -6,7 +6,9 @@ import lodashOrderBy from 'lodash/orderBy';
import Str from 'expensify-common/lib/str';
import ONYXKEYS from '../ONYXKEYS';
import CONST from '../CONST';
-import {getReportParticipantsTitle, isDefaultRoom, getDefaultRoomSubtitle} from './reportUtils';
+import {
+ getReportParticipantsTitle, isDefaultRoom, getDefaultRoomSubtitle, isArchivedRoom,
+} from './reportUtils';
import {translate} from './translate';
import Permissions from './Permissions';
import md5 from './md5';
@@ -250,6 +252,7 @@ function createOption(personalDetailList, report, draftComments, {
isIOUReportOwner: lodashGet(iouReport, 'ownerEmail', '') === currentUserLogin,
iouReportAmount: lodashGet(iouReport, 'total', 0),
isDefaultChatRoom,
+ isArchivedRoom: isArchivedRoom(report),
};
}
diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js
index 75c82c8a3eb5d..a5f583edb08a2 100644
--- a/src/libs/actions/Report.js
+++ b/src/libs/actions/Report.js
@@ -19,7 +19,7 @@ import * as API from '../API';
import CONST from '../../CONST';
import Log from '../Log';
import {
- isConciergeChatReport, isDefaultRoom, isReportMessageAttachment, sortReportsByLastVisited,
+ isConciergeChatReport, isDefaultRoom, isReportMessageAttachment, sortReportsByLastVisited, isArchivedRoom,
} from '../reportUtils';
import Timers from '../Timers';
import {dangerouslyGetReportActionsMaxSequenceNumber, isReportMissingActions} from './ReportActions';
@@ -138,7 +138,13 @@ function getParticipantEmailsFromReport({sharedReportList}) {
*/
function getChatReportName(fullReport, chatType) {
if (isDefaultRoom({chatType})) {
- return `#${fullReport.reportName}`;
+ return `#${fullReport.reportName}${(isArchivedRoom({
+ chatType,
+ stateNum: fullReport.stateNum,
+ statusNum: fullReport.reportStatus,
+ })
+ ? ` (${translateLocal('common.deleted')})`
+ : '')}`;
}
const {sharedReportList} = fullReport;
@@ -181,6 +187,9 @@ function getSimplifiedReportObject(report) {
? lodashGet(report, ['reportNameValuePairs', 'notificationPreferences', currentUserAccountID], 'daily')
: '';
+ // Used for archived rooms, will store the policy name that the room used to belong to.
+ const oldPolicyName = lodashGet(report, ['reportNameValuePairs', 'oldPolicyName'], '');
+
return {
reportID: report.reportID,
reportName,
@@ -201,6 +210,9 @@ function getSimplifiedReportObject(report) {
lastActorEmail,
hasOutstandingIOU: false,
notificationPreference,
+ stateNum: report.state,
+ statusNum: report.status,
+ oldPolicyName,
};
}
diff --git a/src/libs/reportUtils.js b/src/libs/reportUtils.js
index 45eee67217ada..66f9c4dbae8f6 100644
--- a/src/libs/reportUtils.js
+++ b/src/libs/reportUtils.js
@@ -102,6 +102,21 @@ function isDefaultRoom(report) {
], lodashGet(report, ['chatType'], ''));
}
+/**
+ * Whether the provided report is an archived room
+ * @param {Object} report
+ * @param {Number} report.stateNum
+ * @param {Number} report.statusNum
+ * @returns {Boolean}
+ */
+function isArchivedRoom(report) {
+ if (!isDefaultRoom(report)) {
+ return false;
+ }
+
+ return report.statusNum === 2 && report.stateNum === 2;
+}
+
/**
* Get either the policyName or domainName the chat is tied to
* @param {Object} report
@@ -116,6 +131,9 @@ function getDefaultRoomSubtitle(report, policiesMap) {
// The domainAll rooms are just #domainName, so we ignore the prefix '#' to get the domainName
return report.reportName.substring(1);
}
+ if (isArchivedRoom(report)) {
+ return report.oldPolicyName;
+ }
return lodashGet(
policiesMap,
[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, 'name'],
@@ -143,5 +161,6 @@ export {
sortReportsByLastVisited,
isDefaultRoom,
getDefaultRoomSubtitle,
+ isArchivedRoom,
isConciergeChatReport,
};
diff --git a/src/pages/ReportDetailsPage.js b/src/pages/ReportDetailsPage.js
index 16327accd60a3..38229dc46bfb5 100644
--- a/src/pages/ReportDetailsPage.js
+++ b/src/pages/ReportDetailsPage.js
@@ -15,7 +15,7 @@ import HeaderWithCloseButton from '../components/HeaderWithCloseButton';
import styles from '../styles/styles';
import DisplayNames from '../components/DisplayNames';
import {getPersonalDetailsForLogins} from '../libs/OptionsListUtils';
-import {getDefaultRoomSubtitle, isDefaultRoom} from '../libs/reportUtils';
+import {getDefaultRoomSubtitle, isDefaultRoom, isArchivedRoom} from '../libs/reportUtils';
import {participantPropTypes} from './home/sidebar/optionPropTypes';
import Picker from '../components/Picker';
import {updateNotificationPreference} from '../libs/actions/Report';
@@ -88,14 +88,15 @@ class ReportDetailsPage extends Component {
},
};
- this.menuItems = [
- {
- translationKey: 'reportDetailsPage.members',
- icon: Users,
- subtitle: props.report.participants.length,
- action: () => { Navigation.navigate(ROUTES.getReportParticipantsRoute(props.report.reportID)); },
- },
- ];
+ this.menuItems = isArchivedRoom(this.props.report) ? []
+ : [
+ {
+ translationKey: 'reportDetailsPage.members',
+ icon: Users,
+ subtitle: props.report.participants.length,
+ action: () => { Navigation.navigate(ROUTES.getReportParticipantsRoute(props.report.reportID)); },
+ },
+ ];
}
render() {
@@ -128,6 +129,7 @@ class ReportDetailsPage extends Component {
>
-
-
- {this.props.translate('common.notifications')}
-
-
-
-
- {this.props.translate('reportDetailsPage.notificationPreferencesDescription')}
-
-
- {
- updateNotificationPreference(
- this.props.report.reportID,
- notificationPreference,
- );
- }}
- items={Object.values(this.notificationPreferencesOptions)}
- value={this.props.report.notificationPreference}
- />
+ {!isArchivedRoom(this.props.report) && (
+
+
+
+ {this.props.translate('common.notifications')}
+
+
+
+
+ {this.props.translate('reportDetailsPage.notificationPreferencesDescription')}
+
+
+ {
+ updateNotificationPreference(
+ this.props.report.reportID,
+ notificationPreference,
+ );
+ }}
+ items={Object.values(this.notificationPreferencesOptions)}
+ value={this.props.report.notificationPreference}
+ />
+
+
-
+ )}
{this.menuItems.map((item) => {
const keyTitle = item.translationKey ? this.props.translate(item.translationKey) : item.title;
diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js
index c995a411d9709..c1f4e7d63c006 100644
--- a/src/pages/home/HeaderView.js
+++ b/src/pages/home/HeaderView.js
@@ -23,7 +23,7 @@ import VideoChatButtonAndMenu from '../../components/VideoChatButtonAndMenu';
import IOUBadge from '../../components/IOUBadge';
import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize';
import CONST from '../../CONST';
-import {getDefaultRoomSubtitle, isDefaultRoom} from '../../libs/reportUtils';
+import {getDefaultRoomSubtitle, isDefaultRoom, isArchivedRoom} from '../../libs/reportUtils';
import Text from '../../components/Text';
const propTypes = {
@@ -122,6 +122,7 @@ const HeaderView = (props) => {
avatarImageURLs={props.report.icons}
secondAvatarStyle={[styles.secondAvatarHovered]}
isDefaultChatRoom={isDefaultChatRoom}
+ isArchivedRoom={isArchivedRoom(props.report)}
/>
@@ -555,7 +574,7 @@ class ReportActionCompose extends React.Component {
onPasteFile={file => displayFileInModal({file})}
shouldClear={this.state.textInputShouldClear}
onClear={() => this.setTextInputShouldClear(false)}
- isDisabled={isComposeDisabled || isBlockedFromConcierge}
+ isDisabled={isComposeDisabled || isBlockedFromConcierge || isArchivedChatRoom}
selection={this.state.selection}
onSelectionChange={this.onSelectionChange}
/>
@@ -594,7 +613,7 @@ class ReportActionCompose extends React.Component {
ref={el => this.emojiPopoverAnchor = el}
onLayout={this.measureEmojiPopoverAnchorPosition}
onPress={this.showEmojiPicker}
- disabled={isBlockedFromConcierge}
+ disabled={isBlockedFromConcierge || isArchivedChatRoom}
>
{({hovered, pressed}) => (
diff --git a/src/pages/home/sidebar/OptionRow.js b/src/pages/home/sidebar/OptionRow.js
index 08c8bc1e68497..245e646ad2fe1 100644
--- a/src/pages/home/sidebar/OptionRow.js
+++ b/src/pages/home/sidebar/OptionRow.js
@@ -184,6 +184,7 @@ const OptionRow = ({
: undefined,
]}
isDefaultChatRoom={option.isDefaultChatRoom}
+ isArchivedRoom={option.isArchivedRoom}
/>
)
}