From adab2b4506c713df3ed53668532d92af9d4ced76 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 13 Jul 2021 15:14:43 +1000 Subject: [PATCH 1/3] add Notifications in conversations context menu --- ts/components/ConversationListItem.tsx | 11 +++++++- .../menu/ConversationListItemContextMenu.tsx | 19 +++++++++++++- ts/models/conversation.ts | 7 +++++ ts/state/ducks/conversations.ts | 8 +++++- .../unit/selectors/conversations_test.ts | 26 +++++++++++++++++-- 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/ts/components/ConversationListItem.tsx b/ts/components/ConversationListItem.tsx index ebdd01aee..b17f00bbd 100644 --- a/ts/components/ConversationListItem.tsx +++ b/ts/components/ConversationListItem.tsx @@ -66,6 +66,8 @@ const ConversationListItem = (props: Props) => { type, lastMessage, memberAvatars, + notificationForConvo, + currentNotificationSetting, } = props; const triggerId: string = `conversation-item-${phoneNumber}-ctxmenu`; const key: string = `conversation-item-${phoneNumber}`; @@ -119,7 +121,14 @@ const ConversationListItem = (props: Props) => { - + ); diff --git a/ts/components/session/menu/ConversationListItemContextMenu.tsx b/ts/components/session/menu/ConversationListItemContextMenu.tsx index 740eacfa1..61d39a371 100644 --- a/ts/components/session/menu/ConversationListItemContextMenu.tsx +++ b/ts/components/session/menu/ConversationListItemContextMenu.tsx @@ -1,6 +1,9 @@ import React from 'react'; import { animation, Menu } from 'react-contexify'; -import { ConversationTypeEnum } from '../../../models/conversation'; +import { + ConversationNotificationSettingType, + ConversationTypeEnum, +} from '../../../models/conversation'; import { getBlockMenuItem, @@ -12,8 +15,10 @@ import { getInviteContactMenuItem, getLeaveGroupMenuItem, getMarkAllReadMenuItem, + getNotificationForConvoMenuItem, getPinConversationMenuItem, } from './Menu'; +import { NotificationForConvoOption } from '../../conversation/ConversationHeader'; export type PropsContextConversationItem = { id: string; @@ -26,6 +31,8 @@ export type PropsContextConversationItem = { isKickedFromGroup?: boolean; left?: boolean; theme?: any; + notificationForConvo: Array; + currentNotificationSetting: ConversationNotificationSettingType; }; export const ConversationListItemContextMenu = (props: PropsContextConversationItem) => { @@ -39,6 +46,8 @@ export const ConversationListItemContextMenu = (props: PropsContextConversationI type, left, isKickedFromGroup, + notificationForConvo, + currentNotificationSetting, } = props; const isGroup = type === 'group'; @@ -46,6 +55,14 @@ export const ConversationListItemContextMenu = (props: PropsContextConversationI return ( <> + {getNotificationForConvoMenuItem( + isKickedFromGroup, + left, + isBlocked, + notificationForConvo, + currentNotificationSetting, + conversationId + )} {getPinConversationMenuItem(conversationId)} {getBlockMenuItem(isMe, type === ConversationTypeEnum.PRIVATE, isBlocked, conversationId)} {getCopyMenuItem(isPublic, isGroup, conversationId)} diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 5dae6d3c5..79caa9440 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -408,6 +408,13 @@ export class ConversationModel extends Backbone.Model { groupAdmins, members, isPinned: this.isPinned(), + notificationForConvo: 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}`) }; + }), + currentNotificationSetting: this.get('triggerNotificationsFor'), }; } diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index eb20669f9..2fea3d79f 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -5,8 +5,12 @@ import { createAsyncThunk } from '@reduxjs/toolkit'; import { getConversationController } from '../../session/conversations'; import { MessageModel } from '../../models/message'; import { getMessagesByConversation } from '../../data/data'; -import { ConversationTypeEnum } from '../../models/conversation'; +import { + ConversationNotificationSettingType, + ConversationTypeEnum, +} from '../../models/conversation'; import { MessageDeliveryStatus } from '../../models/messageType'; +import { NotificationForConvoOption } from '../../components/conversation/ConversationHeader'; // State @@ -83,6 +87,8 @@ export interface ConversationType { groupAdmins?: Array; // admins for closed groups and moderators for open groups members?: Array; // members for closed groups only isPinned: boolean; + notificationForConvo: Array; + currentNotificationSetting: ConversationNotificationSettingType; } export type ConversationLookupType = { diff --git a/ts/test/session/unit/selectors/conversations_test.ts b/ts/test/session/unit/selectors/conversations_test.ts index 06b494aa5..ea673cdf3 100644 --- a/ts/test/session/unit/selectors/conversations_test.ts +++ b/ts/test/session/unit/selectors/conversations_test.ts @@ -1,5 +1,8 @@ import { assert } from 'chai'; -import { ConversationTypeEnum } from '../../../../models/conversation'; +import { + ConversationNotificationSetting, + ConversationTypeEnum, +} from '../../../../models/conversation'; import { ConversationLookupType } from '../../../../state/ducks/conversations'; import { @@ -28,6 +31,8 @@ describe('state/selectors/conversations', () => { isKickedFromGroup: false, left: false, isPinned: false, + notificationForConvo: [], + currentNotificationSetting: ConversationNotificationSetting[0], }, id2: { id: 'id2', @@ -45,13 +50,14 @@ describe('state/selectors/conversations', () => { isKickedFromGroup: false, left: false, isPinned: false, + notificationForConvo: [], + currentNotificationSetting: ConversationNotificationSetting[0], }, id3: { id: 'id3', activeAt: 20, name: 'C', phoneNumber: 'notused', - type: ConversationTypeEnum.PRIVATE, isMe: false, unreadCount: 1, @@ -62,6 +68,8 @@ describe('state/selectors/conversations', () => { isKickedFromGroup: false, left: false, isPinned: false, + notificationForConvo: [], + currentNotificationSetting: ConversationNotificationSetting[0], }, id4: { id: 'id4', @@ -78,6 +86,8 @@ describe('state/selectors/conversations', () => { isKickedFromGroup: false, left: false, isPinned: false, + notificationForConvo: [], + currentNotificationSetting: ConversationNotificationSetting[0], }, id5: { id: 'id5', @@ -94,6 +104,8 @@ describe('state/selectors/conversations', () => { isKickedFromGroup: false, left: false, isPinned: false, + notificationForConvo: [], + currentNotificationSetting: ConversationNotificationSetting[0], }, }; const comparator = _getConversationComparator(i18n); @@ -126,6 +138,8 @@ describe('state/selectors/conversations', () => { isKickedFromGroup: false, left: false, isPinned: false, + notificationForConvo: [], + currentNotificationSetting: ConversationNotificationSetting[0], }, id2: { id: 'id2', @@ -143,6 +157,8 @@ describe('state/selectors/conversations', () => { isKickedFromGroup: false, left: false, isPinned: false, + notificationForConvo: [], + currentNotificationSetting: ConversationNotificationSetting[0], }, id3: { id: 'id3', @@ -160,6 +176,8 @@ describe('state/selectors/conversations', () => { isKickedFromGroup: false, left: false, isPinned: true, + notificationForConvo: [], + currentNotificationSetting: ConversationNotificationSetting[0], }, id4: { id: 'id4', @@ -176,6 +194,8 @@ describe('state/selectors/conversations', () => { isKickedFromGroup: false, left: false, isPinned: true, + notificationForConvo: [], + currentNotificationSetting: ConversationNotificationSetting[0], }, id5: { id: 'id5', @@ -192,6 +212,8 @@ describe('state/selectors/conversations', () => { isKickedFromGroup: false, left: false, isPinned: false, + notificationForConvo: [], + currentNotificationSetting: ConversationNotificationSetting[0], }, }; const comparator = _getConversationComparator(i18n); From 5d7d58fe05b59d1c564fbc284f73d8544b620c9f Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 13 Jul 2021 15:34:56 +1000 Subject: [PATCH 2/3] move NotificationForConvoOption declaration + getConversationNotificationSettingType created as used twice --- .../conversation/ConversationHeader.tsx | 6 +----- .../conversation/SessionConversation.tsx | 8 +------- .../session/menu/ConversationHeaderMenu.tsx | 4 +++- .../menu/ConversationListItemContextMenu.tsx | 2 +- ts/components/session/menu/Menu.tsx | 3 ++- ts/models/conversation.ts | 19 ++++++++++++------- ts/state/ducks/conversations.ts | 6 +++++- 7 files changed, 25 insertions(+), 23 deletions(-) diff --git a/ts/components/conversation/ConversationHeader.tsx b/ts/components/conversation/ConversationHeader.tsx index f18548455..45af09034 100644 --- a/ts/components/conversation/ConversationHeader.tsx +++ b/ts/components/conversation/ConversationHeader.tsx @@ -16,17 +16,13 @@ import { import { contextMenu } from 'react-contexify'; import { DefaultTheme, withTheme } from 'styled-components'; import { ConversationNotificationSettingType } from '../../models/conversation'; +import { NotificationForConvoOption } from '../../state/ducks/conversations'; export interface TimerOption { name: string; value: number; } -export interface NotificationForConvoOption { - name: string; - value: ConversationNotificationSettingType; -} - interface Props { id: string; name?: string; diff --git a/ts/components/session/conversation/SessionConversation.tsx b/ts/components/session/conversation/SessionConversation.tsx index dddb87f62..82bdb317e 100644 --- a/ts/components/session/conversation/SessionConversation.tsx +++ b/ts/components/session/conversation/SessionConversation.tsx @@ -352,13 +352,7 @@ export class SessionConversation extends React.Component { const members = conversation.get('members') || []; - // exclude mentions_only settings for private chats as this does not make much sense - 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 notificationForConvo = conversation.getConversationNotificationSettingType(); const headerProps = { id: conversation.id, diff --git a/ts/components/session/menu/ConversationHeaderMenu.tsx b/ts/components/session/menu/ConversationHeaderMenu.tsx index 40b9f97c8..c6cb377bf 100644 --- a/ts/components/session/menu/ConversationHeaderMenu.tsx +++ b/ts/components/session/menu/ConversationHeaderMenu.tsx @@ -13,11 +13,13 @@ import { getLeaveGroupMenuItem, getMarkAllReadMenuItem, getNotificationForConvoMenuItem, + getPinConversationMenuItem, getRemoveModeratorsMenuItem, getUpdateGroupNameMenuItem, } from './Menu'; -import { NotificationForConvoOption, TimerOption } from '../../conversation/ConversationHeader'; +import { TimerOption } from '../../conversation/ConversationHeader'; import { ConversationNotificationSettingType } from '../../../models/conversation'; +import { NotificationForConvoOption } from '../../../state/ducks/conversations'; export type PropsConversationHeaderMenu = { conversationId: string; diff --git a/ts/components/session/menu/ConversationListItemContextMenu.tsx b/ts/components/session/menu/ConversationListItemContextMenu.tsx index 61d39a371..17f5821cb 100644 --- a/ts/components/session/menu/ConversationListItemContextMenu.tsx +++ b/ts/components/session/menu/ConversationListItemContextMenu.tsx @@ -4,6 +4,7 @@ import { ConversationNotificationSettingType, ConversationTypeEnum, } from '../../../models/conversation'; +import { NotificationForConvoOption } from '../../../state/ducks/conversations'; import { getBlockMenuItem, @@ -18,7 +19,6 @@ import { getNotificationForConvoMenuItem, getPinConversationMenuItem, } from './Menu'; -import { NotificationForConvoOption } from '../../conversation/ConversationHeader'; export type PropsContextConversationItem = { id: string; diff --git a/ts/components/session/menu/Menu.tsx b/ts/components/session/menu/Menu.tsx index 9c4886aab..bdfb16a62 100644 --- a/ts/components/session/menu/Menu.tsx +++ b/ts/components/session/menu/Menu.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { getNumberOfPinnedConversations } from '../../../state/selectors/conversations'; import { getFocusedSection } from '../../../state/selectors/section'; -import { NotificationForConvoOption, TimerOption } from '../../conversation/ConversationHeader'; +import { TimerOption } from '../../conversation/ConversationHeader'; import { Item, Submenu } from 'react-contexify'; import { ConversationNotificationSettingType } from '../../../models/conversation'; import { useDispatch, useSelector } from 'react-redux'; @@ -26,6 +26,7 @@ import { } from '../../../interactions/conversationInteractions'; import { SessionButtonColor } from '../SessionButton'; import { ToastUtils } from '../../../session/utils'; +import { NotificationForConvoOption } from '../../../state/ducks/conversations'; const maxNumberOfPinnedConversations = 5; diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 79caa9440..5110bad0f 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -25,6 +25,7 @@ import { actions as conversationActions, ConversationType as ReduxConversationType, LastMessageStatusType, + NotificationForConvoOption, } from '../state/ducks/conversations'; import { ExpirationTimerUpdateMessage } from '../session/messages/outgoing/controlMessage/ExpirationTimerUpdateMessage'; import { TypingMessage } from '../session/messages/outgoing/controlMessage/TypingMessage'; @@ -35,7 +36,6 @@ import { import { GroupInvitationMessage } from '../session/messages/outgoing/visibleMessage/GroupInvitationMessage'; import { ReadReceiptMessage } from '../session/messages/outgoing/controlMessage/receipt/ReadReceiptMessage'; import { OpenGroupUtils } from '../opengroup/utils'; -import { ConversationInteraction } from '../interactions'; import { OpenGroupVisibleMessage } from '../session/messages/outgoing/visibleMessage/OpenGroupVisibleMessage'; import { OpenGroupRequestCommonType } from '../opengroup/opengroupV2/ApiUtil'; import { getOpenGroupV2FromConversationId } from '../opengroup/utils/OpenGroupUtils'; @@ -408,16 +408,21 @@ export class ConversationModel extends Backbone.Model { groupAdmins, members, isPinned: this.isPinned(), - notificationForConvo: 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}`) }; - }), + notificationForConvo: this.getConversationNotificationSettingType(), currentNotificationSetting: this.get('triggerNotificationsFor'), }; } + public getConversationNotificationSettingType(): Array { + // 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) { const existingAdmins = _.uniq(_.sortBy(this.getGroupAdmins())); const newAdmins = _.uniq(_.sortBy(groupAdmins)); diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 2fea3d79f..7ea92c9d9 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -10,7 +10,6 @@ import { ConversationTypeEnum, } from '../../models/conversation'; import { MessageDeliveryStatus } from '../../models/messageType'; -import { NotificationForConvoOption } from '../../components/conversation/ConversationHeader'; // State @@ -91,6 +90,11 @@ export interface ConversationType { currentNotificationSetting: ConversationNotificationSettingType; } +export interface NotificationForConvoOption { + name: string; + value: ConversationNotificationSettingType; +} + export type ConversationLookupType = { [key: string]: ConversationType; }; From 46dc6c6275bc62fe74de0e8d52d5e28dcac55ca6 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 13 Jul 2021 15:38:59 +1000 Subject: [PATCH 3/3] pin conversations added to header menu --- ts/components/session/menu/ConversationHeaderMenu.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/ts/components/session/menu/ConversationHeaderMenu.tsx b/ts/components/session/menu/ConversationHeaderMenu.tsx index c6cb377bf..662379c36 100644 --- a/ts/components/session/menu/ConversationHeaderMenu.tsx +++ b/ts/components/session/menu/ConversationHeaderMenu.tsx @@ -76,6 +76,7 @@ export const ConversationHeaderMenu = (props: PropsConversationHeaderMenu) => { currentNotificationSetting, conversationId )} + {getPinConversationMenuItem(conversationId)} {getBlockMenuItem(isMe, isPrivate, isBlocked, conversationId)} {getCopyMenuItem(isPublic, isGroup, conversationId)}