From 4ddc00c9b6b81d093eff8ad9e405d63fa93c372f Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 6 Jul 2021 13:34:39 +1000 Subject: [PATCH] set a limit numer to pinned conversations --- ts/components/session/SessionInboxView.tsx | 3 ++ ts/components/session/menu/Menu.tsx | 22 +++++++- ts/state/ducks/conversations.ts | 60 ++++++++++++++++++++++ ts/state/selectors/conversations.ts | 4 ++ 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/ts/components/session/SessionInboxView.tsx b/ts/components/session/SessionInboxView.tsx index 900fb9453..e5fc69a87 100644 --- a/ts/components/session/SessionInboxView.tsx +++ b/ts/components/session/SessionInboxView.tsx @@ -90,10 +90,13 @@ export class SessionInboxView extends React.Component { const fullFilledConversations = await Promise.all(filledConversations); + const pinnedConversations = conversations.filter( (conversation) => conversation.isPinned).length; + const initialState: StateType = { conversations: { conversationLookup: makeLookup(fullFilledConversations, 'id'), messages: [], + pinnedConversations: pinnedConversations, }, user: { ourNumber: UserUtils.getOurPubKeyStrFromCache(), diff --git a/ts/components/session/menu/Menu.tsx b/ts/components/session/menu/Menu.tsx index dd59e04a6..6931e8607 100644 --- a/ts/components/session/menu/Menu.tsx +++ b/ts/components/session/menu/Menu.tsx @@ -1,5 +1,7 @@ import React from 'react'; +import { getNumberOfPinnedConversations } from '../../../state/selectors/conversations'; +import { conversationPinned, conversationUnpinned } from '../../../state/ducks/conversations'; import { NotificationForConvoOption, TimerOption } from '../../conversation/ConversationHeader'; import { Item, Submenu } from 'react-contexify'; import { ConversationNotificationSettingType } from '../../../models/conversation'; @@ -22,6 +24,9 @@ import { unblockConvoById, } from '../../../interactions/conversationInteractions'; import { SessionButtonColor } from '../SessionButton'; +import { ToastUtils } from '../../../session/utils'; + +const maxNumberOfPinnedConversations = 5; function showTimerOptions( isPublic: boolean, @@ -132,10 +137,25 @@ export const MenuItemPinConversation = ( const { conversationId } = props; const conversation = getConversationController().get(conversationId); const isPinned = conversation.getIsPinned(); + const dispatch = useDispatch(); + const nbOfAlreadyPinnedConvos = useSelector(getNumberOfPinnedConversations); const togglePinConversation = async () => { - await conversation.setIsPinned(!isPinned); + if (!isPinned && nbOfAlreadyPinnedConvos < maxNumberOfPinnedConversations) { + await conversation.setIsPinned(!isPinned); + dispatch(conversationPinned()); + } else if (isPinned) { + await conversation.setIsPinned(!isPinned); + dispatch(conversationUnpinned()); + } else { + ToastUtils.pushToastWarning( + 'setPasswordSuccessToast', + window.i18n('removePasswordTitle'), + window.i18n('removePasswordToastDescription') + ); + } }; + const menuText = isPinned ? window.i18n('unpinConversation') : window.i18n('pinConversation'); return {menuText}; }; diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index a5ecb17bb..4dd63e3ae 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -93,6 +93,7 @@ export type ConversationsStateType = { conversationLookup: ConversationLookupType; selectedConversation?: string; messages: Array; + pinnedConversations: number; }; async function getMessages( @@ -243,6 +244,14 @@ export type SelectedConversationChangedActionType = { messageId?: string; }; }; +export type ConversationPinnedActionType = { + type: 'CONVERSATION_PINNED'; + payload: null; +}; +export type ConversationUnpinnedActionType = { + type: 'CONVERSATION_UNPINNED'; + payload: null; +}; export type FetchMessagesForConversationType = { type: 'messages/fetchByConversationKey/fulfilled'; @@ -265,6 +274,8 @@ export type ConversationActionType = | MessagesChangedActionType | SelectedConversationChangedActionType | SelectedConversationChangedActionType + | ConversationPinnedActionType + | ConversationUnpinnedActionType | FetchMessagesForConversationType; // Action Creators @@ -282,6 +293,8 @@ export const actions = { messagesChanged, fetchMessagesForConversation, openConversationExternal, + conversationPinned, + conversationUnpinned, }; function conversationAdded(id: string, data: ConversationType): ConversationAddedActionType { @@ -406,6 +419,20 @@ export function openConversationExternal( }; } +export function conversationPinned(): ConversationPinnedActionType { + return { + type: 'CONVERSATION_PINNED', + payload: null, + }; +} + +export function conversationUnpinned(): ConversationUnpinnedActionType { + return { + type: 'CONVERSATION_UNPINNED', + payload: null, + }; +} + // Reducer const toPickFromMessageModel = [ @@ -437,6 +464,7 @@ function getEmptyState(): ConversationsStateType { return { conversationLookup: {}, messages: [], + pinnedConversations: 0, }; } @@ -583,6 +611,30 @@ function handleConversationReset( return state; } +function handleConversationPinned( + state: ConversationsStateType, + action: ConversationPinnedActionType +) { + const { pinnedConversations } = state; + + return { + ...state, + pinnedConversations: pinnedConversations + 1, + }; +} + +function handleConversationUnpinned( + state: ConversationsStateType, + action: ConversationUnpinnedActionType +) { + const { pinnedConversations } = state; + + return { + ...state, + pinnedConversations: (pinnedConversations > 0) ? pinnedConversations - 1 : 0, + }; +} + // tslint:disable: cyclomatic-complexity // tslint:disable: max-func-body-length export function reducer( @@ -691,5 +743,13 @@ export function reducer( return handleConversationReset(state, action); } + if (action.type === 'CONVERSATION_PINNED') { + return handleConversationPinned(state, action); + } + + if (action.type === 'CONVERSATION_UNPINNED') { + return handleConversationUnpinned(state, action); + } + return state; } diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index b054f312a..d25b23e96 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -213,3 +213,7 @@ export const getMe = createSelector( export const getUnreadMessageCount = createSelector(getLeftPaneLists, (state): number => { return state.unreadCount; }); + +export const getNumberOfPinnedConversations = createSelector(getConversations, (state): number => { + return state.pinnedConversations; +});