diff --git a/app/components/announcement_banner/__snapshots__/announcement_banner.test.js.snap b/app/components/announcement_banner/__snapshots__/announcement_banner.test.js.snap
index 9163f2a2e..f40c2d932 100644
--- a/app/components/announcement_banner/__snapshots__/announcement_banner.test.js.snap
+++ b/app/components/announcement_banner/__snapshots__/announcement_banner.test.js.snap
@@ -10,6 +10,8 @@ ShallowWrapper {
bannerEnabled={true}
bannerText="Banner Text"
bannerTextColor="#fff"
+ navigator={Object {}}
+ theme={Object {}}
/>,
Symbol(enzyme.__renderer__): Object {
"batchedUpdates": [Function],
@@ -362,6 +364,8 @@ ShallowWrapper {
bannerEnabled={false}
bannerText="Banner Text"
bannerTextColor="#fff"
+ navigator={Object {}}
+ theme={Object {}}
/>,
Symbol(enzyme.__renderer__): Object {
"batchedUpdates": [Function],
diff --git a/app/components/announcement_banner/announcement_banner.test.js b/app/components/announcement_banner/announcement_banner.test.js
index db0e313e8..1dfcc393a 100644
--- a/app/components/announcement_banner/announcement_banner.test.js
+++ b/app/components/announcement_banner/announcement_banner.test.js
@@ -17,6 +17,8 @@ describe('AnnouncementBanner', () => {
bannerEnabled: true,
bannerText: 'Banner Text',
bannerTextColor: '#fff',
+ navigator: {},
+ theme: {},
};
test('should match snapshot', () => {
diff --git a/app/components/channel_icon.js b/app/components/channel_icon.js
index e814eba39..59c1a10e3 100644
--- a/app/components/channel_icon.js
+++ b/app/components/channel_icon.js
@@ -25,6 +25,7 @@ export default class ChannelIcon extends React.PureComponent {
teammateDeletedAt: PropTypes.number,
theme: PropTypes.object.isRequired,
type: PropTypes.string.isRequired,
+ isArchived: PropTypes.bool.isRequired,
};
static defaultProps = {
@@ -45,6 +46,7 @@ export default class ChannelIcon extends React.PureComponent {
teammateDeletedAt,
theme,
type,
+ isArchived,
} = this.props;
const style = getStyleSheet(theme);
@@ -76,8 +78,14 @@ export default class ChannelIcon extends React.PureComponent {
}
let icon;
-
- if (type === General.OPEN_CHANNEL) {
+ if (isArchived) {
+ icon = (
+
+ );
+ } else if (type === General.OPEN_CHANNEL) {
icon = (
{
+ const {defaultChannel, channelId, onCloseChannel} = this.props;
+ const {setChannelDisplayName, setChannelLoading} = this.props.actions;
+ setChannelLoading(true);
+ setChannelDisplayName(defaultChannel.display_name);
+ EventEmitter.emit('switch_channel', defaultChannel, channelId);
+ if (onCloseChannel) {
+ onCloseChannel();
+ }
+ };
+
+ archivedView = (theme, style) => {
+ return (
+
+
+ );
+ };
+
render() {
const {intl} = this.context;
const {
@@ -463,6 +503,7 @@ export default class PostTextbox extends PureComponent {
navigator,
rootId,
theme,
+ channelIsArchived,
} = this.props;
const style = getStyleSheet(theme);
@@ -528,7 +569,7 @@ export default class PostTextbox extends PureComponent {
value={this.state.value}
rootId={rootId}
/>
-
+ {!channelIsArchived &&
{!channelIsReadOnly && attachmentButton}
{this.renderSendButton()}
-
+ }
+ {channelIsArchived && this.archivedView(theme, style)}
);
}
@@ -624,5 +666,31 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
alignItems: 'center',
justifyContent: 'center',
},
+ archivedWrapper: {
+ paddingLeft: 20,
+ paddingRight: 20,
+ paddingTop: 10,
+ paddingBottom: 10,
+ borderTopWidth: 1,
+ borderTopColor: changeOpacity(theme.centerChannelColor, 0.20),
+ },
+ archivedText: {
+ textAlign: 'center',
+ color: theme.centerChannelColor,
+ },
+ closeButton: {
+ backgroundColor: theme.buttonBg,
+ alignItems: 'center',
+ paddingTop: 5,
+ paddingBottom: 5,
+ borderRadius: 4,
+ marginTop: 10,
+ height: 40,
+ },
+ closeButtonText: {
+ marginTop: 7,
+ color: 'white',
+ fontWeight: 'bold',
+ },
};
});
diff --git a/app/components/reactions/index.js b/app/components/reactions/index.js
index 01defaa1b..4ec98224d 100644
--- a/app/components/reactions/index.js
+++ b/app/components/reactions/index.js
@@ -23,10 +23,14 @@ function makeMapStateToProps() {
const post = getPost(state, ownProps.postId);
const channel = getChannel(state, post.channel_id) || {};
const teamId = channel.team_id;
+ const channelIsArchived = channel.delete_at !== 0;
let canAddReaction = true;
let canRemoveReaction = true;
- if (hasNewPermissions(state)) {
+ if (channelIsArchived) {
+ canAddReaction = false;
+ canRemoveReaction = false;
+ } else if (hasNewPermissions(state)) {
canAddReaction = haveIChannelPermission(state, {
team: teamId,
channel: post.channel_id,
diff --git a/app/components/reactions/reactions.js b/app/components/reactions/reactions.js
index bf844da4c..d2d5c9296 100644
--- a/app/components/reactions/reactions.js
+++ b/app/components/reactions/reactions.js
@@ -68,25 +68,28 @@ export default class Reactions extends PureComponent {
};
render() {
- const {position, reactions} = this.props;
+ const {position, reactions, canAddReaction} = this.props;
const styles = getStyleSheet(this.props.theme);
if (!reactions.size) {
return null;
}
- const addMoreReactions = (
-
-
-
- );
+ let addMoreReactions = null;
+ if (canAddReaction) {
+ addMoreReactions = (
+
+
+
+ );
+ }
const reactionElements = [];
switch (position) {
diff --git a/app/components/sidebars/main/channels_list/channel_item/__snapshots__/channel_item.test.js.snap b/app/components/sidebars/main/channels_list/channel_item/__snapshots__/channel_item.test.js.snap
index b48b1eeb9..0fcd3bb59 100644
--- a/app/components/sidebars/main/channels_list/channel_item/__snapshots__/channel_item.test.js.snap
+++ b/app/components/sidebars/main/channels_list/channel_item/__snapshots__/channel_item.test.js.snap
@@ -9,6 +9,7 @@ ShallowWrapper {
currentChannelId="current_channel_id"
displayName="display_name"
fake={false}
+ isArchived={false}
isChannelMuted={false}
isMyUser={true}
isUnread={true}
@@ -81,6 +82,7 @@ ShallowWrapper {
);
diff --git a/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js b/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js
index ac661e812..3ce307c00 100644
--- a/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js
+++ b/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js
@@ -34,6 +34,7 @@ describe('ChannelItem', () => {
sidebarTextHoverBg: '#aaa',
},
unreadMsgs: 1,
+ isArchived: false,
};
test('should match snapshot', () => {
diff --git a/app/components/sidebars/main/channels_list/channel_item/index.js b/app/components/sidebars/main/channels_list/channel_item/index.js
index f70703d23..2e0e1435d 100644
--- a/app/components/sidebars/main/channels_list/channel_item/index.js
+++ b/app/components/sidebars/main/channels_list/channel_item/index.js
@@ -72,6 +72,7 @@ function makeMapStateToProps() {
theme: getTheme(state),
type: channel.type,
unreadMsgs,
+ isArchived: channel.delete_at !== 0,
};
};
}
diff --git a/app/screens/channel/channel_nav_bar/channel_title/channel_title.js b/app/screens/channel/channel_nav_bar/channel_title/channel_title.js
index d4fee0e86..f50f7f861 100644
--- a/app/screens/channel/channel_nav_bar/channel_title/channel_title.js
+++ b/app/screens/channel/channel_nav_bar/channel_title/channel_title.js
@@ -20,6 +20,7 @@ export default class ChannelTitle extends PureComponent {
isChannelMuted: PropTypes.bool,
onPress: PropTypes.func,
theme: PropTypes.object,
+ isArchived: PropTypes.bool,
};
static defaultProps = {
@@ -28,6 +29,19 @@ export default class ChannelTitle extends PureComponent {
theme: {},
};
+ archiveIcon(style) {
+ let content = null;
+ if (this.props.isArchived) {
+ content = (
+
+ );
+ }
+ return content;
+ }
+
render() {
const {currentChannelName, displayName, isChannelMuted, onPress, theme} = this.props;
const channelName = displayName || currentChannelName;
@@ -60,6 +74,7 @@ export default class ChannelTitle extends PureComponent {
onPress={onPress}
>
+ {this.archiveIcon(style)}
{
opacity: 0.6,
marginLeft: 0,
},
+ archiveIcon: {
+ fontSize: 17,
+ color: theme.sidebarHeaderTextColor,
+ paddingRight: 7,
+ },
};
});
diff --git a/app/screens/channel/channel_nav_bar/channel_title/index.js b/app/screens/channel/channel_nav_bar/channel_title/index.js
index d63620da4..cdf290a20 100644
--- a/app/screens/channel/channel_nav_bar/channel_title/index.js
+++ b/app/screens/channel/channel_nav_bar/channel_title/index.js
@@ -15,6 +15,7 @@ function mapStateToProps(state) {
return {
currentChannelName: currentChannel ? currentChannel.display_name : '',
+ isArchived: currentChannel ? currentChannel.delete_at !== 0 : false,
displayName: state.views.channel.displayName,
isChannelMuted: isChannelMuted(myChannelMember),
theme: getTheme(state),
diff --git a/app/screens/channel_info/channel_info.js b/app/screens/channel_info/channel_info.js
index 25dd6a4bf..7a0797cfe 100644
--- a/app/screens/channel_info/channel_info.js
+++ b/app/screens/channel_info/channel_info.js
@@ -328,20 +328,105 @@ export default class ChannelInfo extends PureComponent {
return isDirectMessage || isGroupMessage;
};
+ actionsRows = (style, channelIsArchived) => {
+ const {
+ currentChannelMemberCount,
+ canManageUsers,
+ canEditChannel,
+ theme,
+ } = this.props;
+
+ if (channelIsArchived) {
+ return null;
+ }
+
+ return (
+
+
+
+ {
+
+ /**
+ true}
+ defaultMessage='Notification Preferences'
+ icon='bell-o'
+ textId='channel_header.notificationPreferences'
+ theme={theme}
+ />
+
+ **/
+ }
+ {this.renderViewOrManageMembersRow() &&
+
+
+
+
+ }
+ {canManageUsers &&
+
+
+
+
+ }
+ {canEditChannel && (
+
+
+
+
+ )}
+
+ );
+ };
+
render() {
const {
canDeleteChannel,
currentChannel,
currentChannelCreatorName,
currentChannelMemberCount,
- canManageUsers,
- canEditChannel,
navigator,
status,
theme,
} = this.props;
const style = getStyleSheet(theme);
+ const channelIsArchived = currentChannel.delete_at !== 0;
let i18nId;
let defaultMessage;
@@ -363,93 +448,24 @@ export default class ChannelInfo extends PureComponent {
style={style.scrollView}
>
{currentChannel.hasOwnProperty('id') &&
-
+
}
-
-
-
- {
-
- /**
- true}
- defaultMessage='Notification Preferences'
- icon='bell-o'
- textId='channel_header.notificationPreferences'
- theme={theme}
- />
-
- **/
- }
- {this.renderViewOrManageMembersRow() &&
-
-
-
-
- }
- {canManageUsers &&
-
-
-
-
- }
- {canEditChannel && (
-
-
-
-
- )}
+ {this.actionsRows(style, channelIsArchived)}
{this.renderLeaveOrDeleteChannelRow() &&
-
}
- {this.renderLeaveOrDeleteChannelRow() && canDeleteChannel &&
+ {this.renderLeaveOrDeleteChannelRow() && canDeleteChannel && !channelIsArchived &&
}
{this.renderCloseDirect() &&
-
-
-
+
+
+
}
diff --git a/app/screens/permalink/index.js b/app/screens/permalink/index.js
index 7480e13da..fd48f4c32 100644
--- a/app/screens/permalink/index.js
+++ b/app/screens/permalink/index.js
@@ -44,6 +44,7 @@ function makeMapStateToProps() {
return {
channelId: channel ? channel.id : '',
+ channelIsArchived: channel ? channel.delete_at !== 0 : false,
channelName: channel ? channel.display_name : '',
channelTeamId: channel ? channel.team_id : '',
currentTeamId: getCurrentTeamId(state),
diff --git a/app/screens/permalink/permalink.js b/app/screens/permalink/permalink.js
index 7c7d29a3b..a66969581 100644
--- a/app/screens/permalink/permalink.js
+++ b/app/screens/permalink/permalink.js
@@ -12,6 +12,7 @@ import {
import {intlShape} from 'react-intl';
import * as Animatable from 'react-native-animatable';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
+import AwesomeIcon from 'react-native-vector-icons/FontAwesome';
import {General} from 'mattermost-redux/constants';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
@@ -59,6 +60,7 @@ export default class Permalink extends PureComponent {
setChannelLoading: PropTypes.func.isRequired,
}).isRequired,
channelId: PropTypes.string,
+ channelIsArchived: PropTypes.bool,
channelName: PropTypes.string,
channelTeamId: PropTypes.string,
currentTeamId: PropTypes.string.isRequired,
@@ -301,6 +303,20 @@ export default class Permalink extends PureComponent {
}
};
+ archivedIcon = (style) => {
+ let ico = null;
+ if (this.props.channelIsArchived) {
+ ico = (
+
+ {' '}
+ );
+ }
+ return ico;
+ };
+
render() {
const {
currentUserId,
@@ -386,6 +402,7 @@ export default class Permalink extends PureComponent {
numberOfLines={1}
style={style.title}
>
+ {this.archivedIcon(style)}
{title}
@@ -492,5 +509,10 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
color: changeOpacity(theme.centerChannelColor, 0.4),
fontSize: 15,
},
+ archiveIcon: {
+ color: theme.centerChannelColor,
+ fontSize: 16,
+ paddingRight: 20,
+ },
};
});
diff --git a/app/screens/search/index.js b/app/screens/search/index.js
index 19c7e51a4..46e4727b9 100644
--- a/app/screens/search/index.js
+++ b/app/screens/search/index.js
@@ -6,7 +6,7 @@ import {connect} from 'react-redux';
import {selectFocusedPostId, selectPost} from 'mattermost-redux/actions/posts';
import {clearSearch, removeSearchTerms, searchPosts} from 'mattermost-redux/actions/search';
-import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
+import {getCurrentChannelId, filterPostIds} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
@@ -19,9 +19,11 @@ import Search from './search';
function makeMapStateToProps() {
const preparePostIds = makePreparePostIdsForSearchPosts();
+ const filterPostIdsByDeletedChannels = filterPostIds((c) => c && c.delete_at !== 0);
return (state) => {
const postIds = preparePostIds(state, state.entities.search.results);
+
const currentTeamId = getCurrentTeamId(state);
const currentChannelId = getCurrentChannelId(state);
const {recent} = state.entities.search;
@@ -32,6 +34,7 @@ function makeMapStateToProps() {
currentChannelId,
isLandscape: isLandscape(state),
postIds,
+ archivedPostIds: filterPostIdsByDeletedChannels(state, postIds),
recent: recent[currentTeamId],
searchingStatus: searchRequest.status,
theme: getTheme(state),
diff --git a/app/screens/search/search.js b/app/screens/search/search.js
index 7e17ba525..c398e120a 100644
--- a/app/screens/search/search.js
+++ b/app/screens/search/search.js
@@ -56,10 +56,10 @@ export default class Search extends PureComponent {
selectPost: PropTypes.func.isRequired,
}).isRequired,
currentTeamId: PropTypes.string.isRequired,
- currentChannelId: PropTypes.string.isRequired,
isLandscape: PropTypes.bool.isRequired,
navigator: PropTypes.object,
postIds: PropTypes.array,
+ archivedPostIds: PropTypes.arrayOf(PropTypes.string),
recent: PropTypes.array.isRequired,
searchingStatus: PropTypes.string,
theme: PropTypes.object.isRequired,
@@ -68,6 +68,7 @@ export default class Search extends PureComponent {
static defaultProps = {
postIds: [],
recent: [],
+ archivedPostIds: [],
};
static contextTypes = {
@@ -294,6 +295,30 @@ export default class Search extends PureComponent {
);
};
+ archivedIndicator = (postID, style) => {
+ const channelIsArchived = this.props.archivedPostIds.includes(postID);
+ let archivedIndicator = null;
+ if (channelIsArchived) {
+ archivedIndicator = (
+
+
+
+ {' '}
+
+
+
+ );
+ }
+ return archivedIndicator;
+ };
+
renderPost = ({item, index}) => {
const {postIds, theme} = this.props;
const {managedConfig} = this.state;
@@ -325,6 +350,7 @@ export default class Search extends PureComponent {
return (
+ {this.archivedIndicator(postIds[index], style)}
{
@@ -749,6 +775,16 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
searching: {
marginTop: 65,
},
+ archivedIndicator: {
+ alignItems: 'flex-end',
+ width: 150,
+ alignSelf: 'flex-end',
+ marginTop: -17,
+ marginRight: 10,
+ },
+ archivedText: {
+ color: changeOpacity(theme.centerChannelColor, 0.4),
+ },
};
});
diff --git a/app/screens/thread/index.js b/app/screens/thread/index.js
index 2a6820be1..099c7b32a 100644
--- a/app/screens/thread/index.js
+++ b/app/screens/thread/index.js
@@ -27,6 +27,7 @@ function makeMapStateToProps() {
rootId: ownProps.rootId,
postIds: getPostIdsForThread(state, ownProps.rootId),
theme: getTheme(state),
+ channelIsArchived: channel ? channel.delete_at !== 0 : false,
};
};
}
diff --git a/app/screens/thread/thread.js b/app/screens/thread/thread.js
index d1e9ad988..163af06db 100644
--- a/app/screens/thread/thread.js
+++ b/app/screens/thread/thread.js
@@ -30,6 +30,7 @@ class Thread extends PureComponent {
rootId: PropTypes.string.isRequired,
theme: PropTypes.object.isRequired,
postIds: PropTypes.array.isRequired,
+ channelIsArchived: PropTypes.bool,
};
state = {};
@@ -95,6 +96,23 @@ class Thread extends PureComponent {
return null;
}
+ onCloseChannel = () => {
+ this.props.navigator.resetTo({
+ screen: 'Channel',
+ title: '',
+ animated: false,
+ backButtonTitle: '',
+ navigatorStyle: {
+ animated: true,
+ animationType: 'fade',
+ navBarHidden: true,
+ statusBarHidden: false,
+ statusBarHideWithNavBar: false,
+ screenBackgroundColor: 'transparent',
+ },
+ });
+ }
+
render() {
const {
channelId,
@@ -103,6 +121,7 @@ class Thread extends PureComponent {
postIds,
rootId,
theme,
+ channelIsArchived,
} = this.props;
const style = getStyle(theme);
@@ -127,9 +146,11 @@ class Thread extends PureComponent {
/>
{this.hasRootPost() &&
}
diff --git a/package-lock.json b/package-lock.json
index d4211ff02..202e0fbb6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10108,8 +10108,8 @@
}
},
"mattermost-redux": {
- "version": "github:mattermost/mattermost-redux#707dc6926ae3eecb4c7b4ae08dca9be17b933568",
- "from": "github:mattermost/mattermost-redux#707dc6926ae3eecb4c7b4ae08dca9be17b933568",
+ "version": "github:mattermost/mattermost-redux#12353bc88f20dde53b6191747790c6a82b8dd527",
+ "from": "github:mattermost/mattermost-redux#12353bc88f20dde53b6191747790c6a82b8dd527",
"requires": {
"deep-equal": "1.0.1",
"eslint-plugin-header": "1.2.0",
diff --git a/package.json b/package.json
index 4c82e5c66..2e4ba775a 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,7 @@
"intl": "1.2.5",
"jail-monkey": "1.0.0",
"jsc-android": "216113.0.3",
- "mattermost-redux": "github:mattermost/mattermost-redux#707dc6926ae3eecb4c7b4ae08dca9be17b933568",
+ "mattermost-redux": "github:mattermost/mattermost-redux#12353bc88f20dde53b6191747790c6a82b8dd527",
"mime-db": "1.33.0",
"prop-types": "15.6.1",
"react": "16.3.2",