Adds muted state to channel list in sidebar (#6042)

* Sorting categories body in the observable

* Adds muted state to channel list in sidebar

* update snapshots

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
Co-authored-by: Shaz Amjad <shaz.amjad@me.com>
This commit is contained in:
Shaz MJ
2022-03-12 00:13:05 +11:00
committed by GitHub
parent 86bd5c5072
commit eec536a61b
9 changed files with 59 additions and 7 deletions

View File

@@ -18,6 +18,7 @@ type ChannelIconProps = {
isArchived?: boolean;
isInfo?: boolean;
isUnread?: boolean;
isMuted?: boolean;
membersCount?: number;
name: string;
shared: boolean;
@@ -73,6 +74,9 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
groupInfo: {
color: theme.centerChannelColor,
},
muted: {
opacity: 0.4,
},
};
});
@@ -82,6 +86,7 @@ const ChannelIcon = ({
isArchived = false,
isInfo = false,
isUnread = false,
isMuted = false,
membersCount = 0,
name,
shared,
@@ -99,6 +104,7 @@ const ChannelIcon = ({
let unreadGroupBox;
let activeGroup;
let unreadGroup;
let mutedStyle;
if (isUnread) {
unreadIcon = styles.iconUnread;
@@ -118,6 +124,10 @@ const ChannelIcon = ({
activeGroup = styles.groupInfo;
}
if (isMuted) {
mutedStyle = styles.muted;
}
let icon;
if (isArchived) {
icon = (
@@ -180,7 +190,7 @@ const ChannelIcon = ({
}
return (
<View style={[styles.container, {width: size, height: size}, style]}>
<View style={[styles.container, {width: size, height: size}, style, mutedStyle]}>
{icon}
</View>
);

View File

@@ -65,6 +65,7 @@ Object {
"width": 24,
},
undefined,
undefined,
]
}
>
@@ -104,6 +105,7 @@ Object {
"paddingLeft": 12,
},
false,
false,
]
}
>

View File

@@ -14,7 +14,7 @@ type Props = {
category: CategoryModel;
};
const extractKey = (item: any) => item;
const extractKey = (item: string) => item;
const CategoryBody = ({currentChannelId, sortedIds, category}: Props) => {
const ChannelItem = useCallback(({item}: {item: string}) => {

View File

@@ -58,6 +58,7 @@ exports[`components/channel_list/categories/body/channel/item should match snaps
"width": 24,
},
undefined,
undefined,
]
}
>
@@ -120,6 +121,7 @@ exports[`components/channel_list/categories/body/channel/item should match snaps
"paddingLeft": 12,
},
false,
false,
]
}
>

View File

@@ -34,6 +34,7 @@ describe('components/channel_list/categories/body/channel/item', () => {
isActive={false}
isOwnDirectMessage={false}
myChannel={myChannel}
isMuted={false}
collapsed={false}
/>,
);

View File

@@ -39,6 +39,9 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
highlight: {
color: theme.sidebarText,
},
muted: {
color: changeOpacity(theme.sidebarText, 0.4),
},
}));
const textStyle = StyleSheet.create({
@@ -50,18 +53,19 @@ type Props = {
channel: Pick<ChannelModel, 'deleteAt' | 'displayName' | 'name' | 'shared' | 'type'>;
isActive: boolean;
isOwnDirectMessage: boolean;
isMuted: boolean;
myChannel: MyChannelModel;
collapsed: boolean;
}
const ChannelListItem = ({channel, isActive, isOwnDirectMessage, myChannel, collapsed}: Props) => {
const ChannelListItem = ({channel, isActive, isOwnDirectMessage, isMuted, myChannel, collapsed}: Props) => {
const {formatMessage} = useIntl();
const theme = useTheme();
const styles = getStyleSheet(theme);
const serverUrl = useServerUrl();
// Make it brighter if it's highlighted, or has unreads
const bright = myChannel.isUnread || myChannel.mentionsCount > 0;
// Make it brighter if it's not muted, and highlighted or has unreads
const bright = !isMuted && (myChannel.isUnread || myChannel.mentionsCount > 0);
const sharedValue = useSharedValue(collapsed && !bright);
@@ -89,7 +93,8 @@ const ChannelListItem = ({channel, isActive, isOwnDirectMessage, myChannel, coll
bright ? textStyle.bright : textStyle.regular,
styles.text,
bright && styles.highlight,
], [bright, styles]);
isMuted && styles.muted,
], [bright, styles, isMuted]);
let displayName = channel.displayName;
if (isOwnDirectMessage) {

View File

@@ -15,6 +15,7 @@ import ChannelListItem from './channel_list_item';
import type {WithDatabaseArgs} from '@typings/database/database';
import type ChannelModel from '@typings/database/models/servers/channel';
import type MyChannelModel from '@typings/database/models/servers/my_channel';
import type MyChannelSettingsModel from '@typings/database/models/servers/my_channel_settings';
import type SystemModel from '@typings/database/models/servers/system';
const {SERVER: {MY_CHANNEL, SYSTEM}} = MM_TABLES;
@@ -27,6 +28,8 @@ const enhance = withObservables(['channelId'], ({channelId, database}: {channelI
);
const channel = myChannel.pipe(switchMap((my) => my.channel.observe()));
const settings = channel.pipe(switchMap((c) => c.settings.observe()));
const isOwnDirectMessage = combineLatest([currentUserId, channel]).pipe(
switchMap(([userId, ch]) => {
if (ch?.type === General.DM_CHANNEL) {
@@ -39,6 +42,9 @@ const enhance = withObservables(['channelId'], ({channelId, database}: {channelI
);
return {
isOwnDirectMessage,
isMuted: settings.pipe(
switchMap((s: MyChannelSettingsModel) => of$(s.notifyProps?.mark_unread === 'mention')),
),
myChannel,
channel: channel.pipe(
switchMap((c: ChannelModel) => of$({

View File

@@ -80,7 +80,13 @@ export default class CategoryModel extends Model implements CategoryInterface {
@lazy channels = this.collections.
get<ChannelModel>(CHANNEL).
query(
Q.on(CATEGORY_CHANNEL, 'category_id', this.id),
Q.experimentalJoinTables([MY_CHANNEL, CATEGORY_CHANNEL]),
Q.on(CATEGORY_CHANNEL,
Q.and(
Q.on(MY_CHANNEL, Q.where('id', Q.notEq(''))),
Q.where('category_id', this.id),
),
),
);
/** myChannels : Retrieves all myChannels that are part of this category */

View File

@@ -28,6 +28,7 @@ class TestHelper {
this.basicChannel = null;
this.basicChannelMember = null;
this.basicMyChannel = null;
this.basicMyChannelSettings = null;
this.basicPost = null;
this.basicRoles = null;
this.basicScheme = null;
@@ -74,6 +75,10 @@ class TestHelper {
channels: [this.basicChannel],
myChannels: [this.basicMyChannel],
});
await operator.handleMyChannelSettings({
prepareRecordsOnly: false,
settings: [this.basicMyChannelSettings],
});
const systems = await prepareCommonSystemValues(operator, {
config: {},
@@ -222,6 +227,20 @@ class TestHelper {
};
};
fakeMyChannelSettings = (channelId) => {
return {
id: channelId,
channel_id: channelId,
notify_props: JSON.stringify({
desktop: 'default',
email: 'default',
mark_unread: 'all',
push: 'default',
ignore_channel_mentions: 'default',
}),
};
};
fakeEmail = () => {
return 'success' + this.generateId() + '@simulator.amazonses.com';
};
@@ -401,6 +420,7 @@ class TestHelper {
this.basicCategoryChannel = this.fakeCategoryChannelWithId(this.basicTeam.id, this.basicCategory.id, this.basicChannel.id);
this.basicChannelMember = this.fakeChannelMember(this.basicUser.id, this.basicChannel.id);
this.basicMyChannel = this.fakeMyChannel(this.basicChannel.id);
this.basicMyChannelSettings = this.fakeMyChannelSettings(this.basicChannel.id);
this.basicPost = {...this.fakePostWithId(this.basicChannel.id), create_at: 1507841118796};
this.basicRoles = {
system_admin: {