Merge pull request #1779 from Brice-W/menu-update

Header and conversation menus updates
pull/1784/head
Audric Ackermann 4 years ago committed by GitHub
commit 7ffb480b64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -66,6 +66,8 @@ const ConversationListItem = (props: Props) => {
type, type,
lastMessage, lastMessage,
memberAvatars, memberAvatars,
notificationForConvo,
currentNotificationSetting,
} = props; } = props;
const triggerId: string = `conversation-item-${phoneNumber}-ctxmenu`; const triggerId: string = `conversation-item-${phoneNumber}-ctxmenu`;
const key: string = `conversation-item-${phoneNumber}`; const key: string = `conversation-item-${phoneNumber}`;
@ -119,7 +121,14 @@ const ConversationListItem = (props: Props) => {
</div> </div>
</div> </div>
<Portal> <Portal>
<ConversationListItemContextMenu id={id} triggerId={triggerId} type={type} isMe={isMe} /> <ConversationListItemContextMenu
id={id}
triggerId={triggerId}
type={type}
isMe={isMe}
notificationForConvo={notificationForConvo}
currentNotificationSetting={currentNotificationSetting}
/>
</Portal> </Portal>
</div> </div>
); );

@ -16,17 +16,13 @@ import {
import { contextMenu } from 'react-contexify'; import { contextMenu } from 'react-contexify';
import { DefaultTheme, withTheme } from 'styled-components'; import { DefaultTheme, withTheme } from 'styled-components';
import { ConversationNotificationSettingType } from '../../models/conversation'; import { ConversationNotificationSettingType } from '../../models/conversation';
import { NotificationForConvoOption } from '../../state/ducks/conversations';
export interface TimerOption { export interface TimerOption {
name: string; name: string;
value: number; value: number;
} }
export interface NotificationForConvoOption {
name: string;
value: ConversationNotificationSettingType;
}
interface Props { interface Props {
id: string; id: string;
name?: string; name?: string;

@ -352,13 +352,7 @@ export class SessionConversation extends React.Component<Props, State> {
const members = conversation.get('members') || []; const members = conversation.get('members') || [];
// exclude mentions_only settings for private chats as this does not make much sense const notificationForConvo = conversation.getConversationNotificationSettingType();
const notificationForConvo = ConversationNotificationSetting.filter(n =>
conversation.isPrivate() ? n !== 'mentions_only' : true
).map((n: ConversationNotificationSettingType) => {
// this link to the notificationForConvo_all, notificationForConvo_mentions_only, ...
return { value: n, name: window.i18n(`notificationForConvo_${n}`) };
});
const headerProps = { const headerProps = {
id: conversation.id, id: conversation.id,

@ -13,11 +13,13 @@ import {
getLeaveGroupMenuItem, getLeaveGroupMenuItem,
getMarkAllReadMenuItem, getMarkAllReadMenuItem,
getNotificationForConvoMenuItem, getNotificationForConvoMenuItem,
getPinConversationMenuItem,
getRemoveModeratorsMenuItem, getRemoveModeratorsMenuItem,
getUpdateGroupNameMenuItem, getUpdateGroupNameMenuItem,
} from './Menu'; } from './Menu';
import { NotificationForConvoOption, TimerOption } from '../../conversation/ConversationHeader'; import { TimerOption } from '../../conversation/ConversationHeader';
import { ConversationNotificationSettingType } from '../../../models/conversation'; import { ConversationNotificationSettingType } from '../../../models/conversation';
import { NotificationForConvoOption } from '../../../state/ducks/conversations';
export type PropsConversationHeaderMenu = { export type PropsConversationHeaderMenu = {
conversationId: string; conversationId: string;
@ -74,6 +76,7 @@ export const ConversationHeaderMenu = (props: PropsConversationHeaderMenu) => {
currentNotificationSetting, currentNotificationSetting,
conversationId conversationId
)} )}
{getPinConversationMenuItem(conversationId)}
{getBlockMenuItem(isMe, isPrivate, isBlocked, conversationId)} {getBlockMenuItem(isMe, isPrivate, isBlocked, conversationId)}
{getCopyMenuItem(isPublic, isGroup, conversationId)} {getCopyMenuItem(isPublic, isGroup, conversationId)}

@ -1,6 +1,10 @@
import React from 'react'; import React from 'react';
import { animation, Menu } from 'react-contexify'; import { animation, Menu } from 'react-contexify';
import { ConversationTypeEnum } from '../../../models/conversation'; import {
ConversationNotificationSettingType,
ConversationTypeEnum,
} from '../../../models/conversation';
import { NotificationForConvoOption } from '../../../state/ducks/conversations';
import { import {
getBlockMenuItem, getBlockMenuItem,
@ -12,6 +16,7 @@ import {
getInviteContactMenuItem, getInviteContactMenuItem,
getLeaveGroupMenuItem, getLeaveGroupMenuItem,
getMarkAllReadMenuItem, getMarkAllReadMenuItem,
getNotificationForConvoMenuItem,
getPinConversationMenuItem, getPinConversationMenuItem,
} from './Menu'; } from './Menu';
@ -26,6 +31,8 @@ export type PropsContextConversationItem = {
isKickedFromGroup?: boolean; isKickedFromGroup?: boolean;
left?: boolean; left?: boolean;
theme?: any; theme?: any;
notificationForConvo: Array<NotificationForConvoOption>;
currentNotificationSetting: ConversationNotificationSettingType;
}; };
export const ConversationListItemContextMenu = (props: PropsContextConversationItem) => { export const ConversationListItemContextMenu = (props: PropsContextConversationItem) => {
@ -39,6 +46,8 @@ export const ConversationListItemContextMenu = (props: PropsContextConversationI
type, type,
left, left,
isKickedFromGroup, isKickedFromGroup,
notificationForConvo,
currentNotificationSetting,
} = props; } = props;
const isGroup = type === 'group'; const isGroup = type === 'group';
@ -46,6 +55,14 @@ export const ConversationListItemContextMenu = (props: PropsContextConversationI
return ( return (
<> <>
<Menu id={triggerId} animation={animation.fade}> <Menu id={triggerId} animation={animation.fade}>
{getNotificationForConvoMenuItem(
isKickedFromGroup,
left,
isBlocked,
notificationForConvo,
currentNotificationSetting,
conversationId
)}
{getPinConversationMenuItem(conversationId)} {getPinConversationMenuItem(conversationId)}
{getBlockMenuItem(isMe, type === ConversationTypeEnum.PRIVATE, isBlocked, conversationId)} {getBlockMenuItem(isMe, type === ConversationTypeEnum.PRIVATE, isBlocked, conversationId)}
{getCopyMenuItem(isPublic, isGroup, conversationId)} {getCopyMenuItem(isPublic, isGroup, conversationId)}

@ -2,7 +2,7 @@ import React from 'react';
import { getNumberOfPinnedConversations } from '../../../state/selectors/conversations'; import { getNumberOfPinnedConversations } from '../../../state/selectors/conversations';
import { getFocusedSection } from '../../../state/selectors/section'; import { getFocusedSection } from '../../../state/selectors/section';
import { NotificationForConvoOption, TimerOption } from '../../conversation/ConversationHeader'; import { TimerOption } from '../../conversation/ConversationHeader';
import { Item, Submenu } from 'react-contexify'; import { Item, Submenu } from 'react-contexify';
import { ConversationNotificationSettingType } from '../../../models/conversation'; import { ConversationNotificationSettingType } from '../../../models/conversation';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
@ -26,6 +26,7 @@ import {
} from '../../../interactions/conversationInteractions'; } from '../../../interactions/conversationInteractions';
import { SessionButtonColor } from '../SessionButton'; import { SessionButtonColor } from '../SessionButton';
import { ToastUtils } from '../../../session/utils'; import { ToastUtils } from '../../../session/utils';
import { NotificationForConvoOption } from '../../../state/ducks/conversations';
const maxNumberOfPinnedConversations = 5; const maxNumberOfPinnedConversations = 5;

@ -25,6 +25,7 @@ import {
actions as conversationActions, actions as conversationActions,
ConversationType as ReduxConversationType, ConversationType as ReduxConversationType,
LastMessageStatusType, LastMessageStatusType,
NotificationForConvoOption,
} from '../state/ducks/conversations'; } from '../state/ducks/conversations';
import { ExpirationTimerUpdateMessage } from '../session/messages/outgoing/controlMessage/ExpirationTimerUpdateMessage'; import { ExpirationTimerUpdateMessage } from '../session/messages/outgoing/controlMessage/ExpirationTimerUpdateMessage';
import { TypingMessage } from '../session/messages/outgoing/controlMessage/TypingMessage'; import { TypingMessage } from '../session/messages/outgoing/controlMessage/TypingMessage';
@ -35,7 +36,6 @@ import {
import { GroupInvitationMessage } from '../session/messages/outgoing/visibleMessage/GroupInvitationMessage'; import { GroupInvitationMessage } from '../session/messages/outgoing/visibleMessage/GroupInvitationMessage';
import { ReadReceiptMessage } from '../session/messages/outgoing/controlMessage/receipt/ReadReceiptMessage'; import { ReadReceiptMessage } from '../session/messages/outgoing/controlMessage/receipt/ReadReceiptMessage';
import { OpenGroupUtils } from '../opengroup/utils'; import { OpenGroupUtils } from '../opengroup/utils';
import { ConversationInteraction } from '../interactions';
import { OpenGroupVisibleMessage } from '../session/messages/outgoing/visibleMessage/OpenGroupVisibleMessage'; import { OpenGroupVisibleMessage } from '../session/messages/outgoing/visibleMessage/OpenGroupVisibleMessage';
import { OpenGroupRequestCommonType } from '../opengroup/opengroupV2/ApiUtil'; import { OpenGroupRequestCommonType } from '../opengroup/opengroupV2/ApiUtil';
import { getOpenGroupV2FromConversationId } from '../opengroup/utils/OpenGroupUtils'; import { getOpenGroupV2FromConversationId } from '../opengroup/utils/OpenGroupUtils';
@ -408,9 +408,21 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
groupAdmins, groupAdmins,
members, members,
isPinned: this.isPinned(), isPinned: this.isPinned(),
notificationForConvo: this.getConversationNotificationSettingType(),
currentNotificationSetting: this.get('triggerNotificationsFor'),
}; };
} }
public getConversationNotificationSettingType(): Array<NotificationForConvoOption> {
// exclude mentions_only settings for private chats as this does not make much sense
return ConversationNotificationSetting.filter(n =>
this.isPrivate() ? n !== 'mentions_only' : true
).map((n: ConversationNotificationSettingType) => {
// this link to the notificationForConvo_all, notificationForConvo_mentions_only, ...
return { value: n, name: window.i18n(`notificationForConvo_${n}`) };
});
}
public async updateGroupAdmins(groupAdmins: Array<string>) { public async updateGroupAdmins(groupAdmins: Array<string>) {
const existingAdmins = _.uniq(_.sortBy(this.getGroupAdmins())); const existingAdmins = _.uniq(_.sortBy(this.getGroupAdmins()));
const newAdmins = _.uniq(_.sortBy(groupAdmins)); const newAdmins = _.uniq(_.sortBy(groupAdmins));

@ -5,7 +5,10 @@ import { createAsyncThunk } from '@reduxjs/toolkit';
import { getConversationController } from '../../session/conversations'; import { getConversationController } from '../../session/conversations';
import { MessageModel } from '../../models/message'; import { MessageModel } from '../../models/message';
import { getMessagesByConversation } from '../../data/data'; import { getMessagesByConversation } from '../../data/data';
import { ConversationTypeEnum } from '../../models/conversation'; import {
ConversationNotificationSettingType,
ConversationTypeEnum,
} from '../../models/conversation';
import { MessageDeliveryStatus } from '../../models/messageType'; import { MessageDeliveryStatus } from '../../models/messageType';
// State // State
@ -83,6 +86,13 @@ export interface ConversationType {
groupAdmins?: Array<string>; // admins for closed groups and moderators for open groups groupAdmins?: Array<string>; // admins for closed groups and moderators for open groups
members?: Array<string>; // members for closed groups only members?: Array<string>; // members for closed groups only
isPinned: boolean; isPinned: boolean;
notificationForConvo: Array<NotificationForConvoOption>;
currentNotificationSetting: ConversationNotificationSettingType;
}
export interface NotificationForConvoOption {
name: string;
value: ConversationNotificationSettingType;
} }
export type ConversationLookupType = { export type ConversationLookupType = {

@ -1,5 +1,8 @@
import { assert } from 'chai'; import { assert } from 'chai';
import { ConversationTypeEnum } from '../../../../models/conversation'; import {
ConversationNotificationSetting,
ConversationTypeEnum,
} from '../../../../models/conversation';
import { ConversationLookupType } from '../../../../state/ducks/conversations'; import { ConversationLookupType } from '../../../../state/ducks/conversations';
import { import {
@ -28,6 +31,8 @@ describe('state/selectors/conversations', () => {
isKickedFromGroup: false, isKickedFromGroup: false,
left: false, left: false,
isPinned: false, isPinned: false,
notificationForConvo: [],
currentNotificationSetting: ConversationNotificationSetting[0],
}, },
id2: { id2: {
id: 'id2', id: 'id2',
@ -45,13 +50,14 @@ describe('state/selectors/conversations', () => {
isKickedFromGroup: false, isKickedFromGroup: false,
left: false, left: false,
isPinned: false, isPinned: false,
notificationForConvo: [],
currentNotificationSetting: ConversationNotificationSetting[0],
}, },
id3: { id3: {
id: 'id3', id: 'id3',
activeAt: 20, activeAt: 20,
name: 'C', name: 'C',
phoneNumber: 'notused', phoneNumber: 'notused',
type: ConversationTypeEnum.PRIVATE, type: ConversationTypeEnum.PRIVATE,
isMe: false, isMe: false,
unreadCount: 1, unreadCount: 1,
@ -62,6 +68,8 @@ describe('state/selectors/conversations', () => {
isKickedFromGroup: false, isKickedFromGroup: false,
left: false, left: false,
isPinned: false, isPinned: false,
notificationForConvo: [],
currentNotificationSetting: ConversationNotificationSetting[0],
}, },
id4: { id4: {
id: 'id4', id: 'id4',
@ -78,6 +86,8 @@ describe('state/selectors/conversations', () => {
isKickedFromGroup: false, isKickedFromGroup: false,
left: false, left: false,
isPinned: false, isPinned: false,
notificationForConvo: [],
currentNotificationSetting: ConversationNotificationSetting[0],
}, },
id5: { id5: {
id: 'id5', id: 'id5',
@ -94,6 +104,8 @@ describe('state/selectors/conversations', () => {
isKickedFromGroup: false, isKickedFromGroup: false,
left: false, left: false,
isPinned: false, isPinned: false,
notificationForConvo: [],
currentNotificationSetting: ConversationNotificationSetting[0],
}, },
}; };
const comparator = _getConversationComparator(i18n); const comparator = _getConversationComparator(i18n);
@ -126,6 +138,8 @@ describe('state/selectors/conversations', () => {
isKickedFromGroup: false, isKickedFromGroup: false,
left: false, left: false,
isPinned: false, isPinned: false,
notificationForConvo: [],
currentNotificationSetting: ConversationNotificationSetting[0],
}, },
id2: { id2: {
id: 'id2', id: 'id2',
@ -143,6 +157,8 @@ describe('state/selectors/conversations', () => {
isKickedFromGroup: false, isKickedFromGroup: false,
left: false, left: false,
isPinned: false, isPinned: false,
notificationForConvo: [],
currentNotificationSetting: ConversationNotificationSetting[0],
}, },
id3: { id3: {
id: 'id3', id: 'id3',
@ -160,6 +176,8 @@ describe('state/selectors/conversations', () => {
isKickedFromGroup: false, isKickedFromGroup: false,
left: false, left: false,
isPinned: true, isPinned: true,
notificationForConvo: [],
currentNotificationSetting: ConversationNotificationSetting[0],
}, },
id4: { id4: {
id: 'id4', id: 'id4',
@ -176,6 +194,8 @@ describe('state/selectors/conversations', () => {
isKickedFromGroup: false, isKickedFromGroup: false,
left: false, left: false,
isPinned: true, isPinned: true,
notificationForConvo: [],
currentNotificationSetting: ConversationNotificationSetting[0],
}, },
id5: { id5: {
id: 'id5', id: 'id5',
@ -192,6 +212,8 @@ describe('state/selectors/conversations', () => {
isKickedFromGroup: false, isKickedFromGroup: false,
left: false, left: false,
isPinned: false, isPinned: false,
notificationForConvo: [],
currentNotificationSetting: ConversationNotificationSetting[0],
}, },
}; };
const comparator = _getConversationComparator(i18n); const comparator = _getConversationComparator(i18n);

Loading…
Cancel
Save