Add draft indicator to the channel item (#2150)

* Add draft indicator to the channel item

* Feedback review
This commit is contained in:
Elias Nahum 2018-09-26 12:17:54 -03:00 committed by GitHub
parent 4cebbfdc94
commit 2567b7dc04
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 196 additions and 21 deletions

View file

@ -19,6 +19,7 @@ export default class ChannelIcon extends React.PureComponent {
isActive: PropTypes.bool,
isInfo: PropTypes.bool,
isUnread: PropTypes.bool,
hasDraft: PropTypes.bool,
membersCount: PropTypes.number,
size: PropTypes.number,
status: PropTypes.string,
@ -40,6 +41,7 @@ export default class ChannelIcon extends React.PureComponent {
isActive,
isUnread,
isInfo,
hasDraft,
membersCount,
size,
status,
@ -85,6 +87,13 @@ export default class ChannelIcon extends React.PureComponent {
style={[style.icon, unreadIcon, activeIcon, {fontSize: size}]}
/>
);
} else if (hasDraft) {
icon = (
<Icon
name='pencil'
style={[style.icon, unreadIcon, activeIcon, {fontSize: size}]}
/>
);
} else if (type === General.OPEN_CHANNEL) {
icon = (
<Icon

View file

@ -7,7 +7,7 @@ exports[`ChannelItem should match snapshot 1`] = `
delayPressOut={100}
onLongPress={[Function]}
onPress={[Function]}
underlayColor="rgba(170,170,170,0.5)"
underlayColor="rgba(69,120,191,0.5)"
>
<Component
style={
@ -36,6 +36,7 @@ exports[`ChannelItem should match snapshot 1`] = `
>
<ChannelIcon
channelId="channel_id"
hasDraft={false}
isActive={false}
isArchived={false}
isInfo={false}
@ -46,10 +47,30 @@ exports[`ChannelItem should match snapshot 1`] = `
teammateDeletedAt={0}
theme={
Object {
"sidebarText": "#aaa",
"sidebarTextActiveBorder": "#aaa",
"sidebarTextActiveColor": "#aaa",
"sidebarTextHoverBg": "#aaa",
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
type="O"
@ -60,7 +81,7 @@ exports[`ChannelItem should match snapshot 1`] = `
style={
Array [
Object {
"color": "rgba(170,170,170,0.4)",
"color": "rgba(255,255,255,0.4)",
"flex": 1,
"fontSize": 14,
"fontWeight": "600",
@ -70,7 +91,7 @@ exports[`ChannelItem should match snapshot 1`] = `
"textAlignVertical": "center",
},
Object {
"color": undefined,
"color": "#ffffff",
},
]
}
@ -88,7 +109,7 @@ exports[`ChannelItem should match snapshot for deactivated user 1`] = `
delayPressOut={100}
onLongPress={[Function]}
onPress={[Function]}
underlayColor="rgba(170,170,170,0.5)"
underlayColor="rgba(69,120,191,0.5)"
>
<Component
style={
@ -117,6 +138,7 @@ exports[`ChannelItem should match snapshot for deactivated user 1`] = `
>
<ChannelIcon
channelId="channel_id"
hasDraft={false}
isActive={false}
isArchived={false}
isInfo={false}
@ -127,10 +149,30 @@ exports[`ChannelItem should match snapshot for deactivated user 1`] = `
teammateDeletedAt={100}
theme={
Object {
"sidebarText": "#aaa",
"sidebarTextActiveBorder": "#aaa",
"sidebarTextActiveColor": "#aaa",
"sidebarTextHoverBg": "#aaa",
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
type="D"
@ -141,7 +183,7 @@ exports[`ChannelItem should match snapshot for deactivated user 1`] = `
style={
Array [
Object {
"color": "rgba(170,170,170,0.4)",
"color": "rgba(255,255,255,0.4)",
"flex": 1,
"fontSize": 14,
"fontWeight": "600",
@ -151,7 +193,109 @@ exports[`ChannelItem should match snapshot for deactivated user 1`] = `
"textAlignVertical": "center",
},
Object {
"color": undefined,
"color": "#ffffff",
},
]
}
/>
</Component>
</Component>
</TouchableHighlight>
</AnimatedComponent>
`;
exports[`ChannelItem should match snapshot with draft 1`] = `
<AnimatedComponent>
<TouchableHighlight
activeOpacity={0.85}
delayPressOut={100}
onLongPress={[Function]}
onPress={[Function]}
underlayColor="rgba(69,120,191,0.5)"
>
<Component
style={
Array [
Object {
"flex": 1,
"flexDirection": "row",
"height": 44,
},
undefined,
]
}
>
<Component
style={
Array [
Object {
"alignItems": "center",
"flex": 1,
"flexDirection": "row",
"paddingLeft": 16,
},
undefined,
]
}
>
<ChannelIcon
channelId="channel_id"
hasDraft={true}
isActive={false}
isArchived={false}
isInfo={false}
isUnread={true}
membersCount={1}
size={16}
status="online"
teammateDeletedAt={0}
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
type="O"
/>
<Component
ellipsizeMode="tail"
numberOfLines={1}
style={
Array [
Object {
"color": "rgba(255,255,255,0.4)",
"flex": 1,
"fontSize": 14,
"fontWeight": "600",
"height": "100%",
"lineHeight": 44,
"paddingRight": 40,
"textAlignVertical": "center",
},
Object {
"color": "#ffffff",
},
]
}

View file

@ -28,6 +28,7 @@ export default class ChannelItem extends PureComponent {
isChannelMuted: PropTypes.bool,
isMyUser: PropTypes.bool,
isUnread: PropTypes.bool,
hasDraft: PropTypes.bool,
mentions: PropTypes.number.isRequired,
navigator: PropTypes.object,
onSelectChannel: PropTypes.func.isRequired,
@ -92,6 +93,7 @@ export default class ChannelItem extends PureComponent {
isChannelMuted,
isMyUser,
isUnread,
hasDraft,
mentions,
shouldHideChannel,
status,
@ -167,6 +169,7 @@ export default class ChannelItem extends PureComponent {
isActive={isActive}
channelId={channelId}
isUnread={isUnread}
hasDraft={hasDraft && channelId !== currentChannelId}
membersCount={displayName.split(',').length}
size={16}
status={status}

View file

@ -4,6 +4,8 @@
import React from 'react';
import {shallow} from 'enzyme';
import Preferences from 'mattermost-redux/constants/preferences';
import ChannelItem from './channel_item.js';
jest.mock('react-intl');
@ -17,6 +19,7 @@ describe('ChannelItem', () => {
isChannelMuted: false,
isMyUser: true,
isUnread: true,
hasDraft: false,
mentions: 0,
navigator: {push: () => {}}, // eslint-disable-line no-empty-function
onSelectChannel: () => {}, // eslint-disable-line no-empty-function
@ -25,12 +28,7 @@ describe('ChannelItem', () => {
status: 'online',
teammateDeletedAt: 0,
type: 'O',
theme: {
sidebarText: '#aaa',
sidebarTextActiveBorder: '#aaa',
sidebarTextActiveColor: '#aaa',
sidebarTextHoverBg: '#aaa',
},
theme: Preferences.THEMES.default,
unreadMsgs: 1,
isArchived: false,
};
@ -56,4 +54,16 @@ describe('ChannelItem', () => {
);
expect(wrapper.getElement()).toMatchSnapshot();
});
test('should match snapshot with draft', () => {
const wrapper = shallow(
<ChannelItem
{...baseProps}
hasDraft={true}
/>,
{context: {intl: {formatMessage: jest.fn()}}},
);
expect(wrapper.getElement()).toMatchSnapshot();
});
});

View file

@ -15,6 +15,8 @@ import {getCurrentUserId, getUser} from 'mattermost-redux/selectors/entities/use
import {isChannelMuted} from 'mattermost-redux/utils/channel_utils';
import {displayUsername} from 'mattermost-redux/utils/user_utils';
import {getDraftForChannel} from 'app/selectors/views';
import ChannelItem from './channel_item';
function makeMapStateToProps() {
@ -22,8 +24,9 @@ function makeMapStateToProps() {
return (state, ownProps) => {
const channel = ownProps.channel || getChannel(state, {id: ownProps.channelId});
const member = getMyChannelMember(state, ownProps.channelId);
const member = getMyChannelMember(state, channel.id);
const currentUserId = getCurrentUserId(state);
const channelDraft = getDraftForChannel(state, channel.id);
let isMyUser = false;
let teammateDeletedAt = 0;
@ -75,6 +78,7 @@ function makeMapStateToProps() {
fake: channel.fake,
isChannelMuted: isChannelMuted(member),
isMyUser,
hasDraft: Boolean(channelDraft.draft || channelDraft.files.length),
mentions: member ? member.mention_count : 0,
shouldHideChannel,
showUnreadForMsgs,

View file

@ -26,6 +26,11 @@ export const getCurrentChannelDraft = createSelector(
}
);
export function getDraftForChannel(state, channelId) {
const drafts = getChannelDrafts(state);
return drafts[channelId] || emptyDraft;
}
export const getThreadDraft = createSelector(
getThreadDrafts,
(state, rootId) => rootId,