From 40566a58a4d7c14ad1f452c3d7dc45d981c3ed03 Mon Sep 17 00:00:00 2001 From: audric Date: Fri, 27 Aug 2021 11:38:02 +1000 Subject: [PATCH] moved the unread indicator to outside of message items --- main.js | 4 +- ts/components/session/SessionSearchInput.tsx | 4 +- .../conversation/SessionMessagesList.tsx | 83 ++++++++--------- .../conversation/SessionMessagesTypes.tsx | 89 ------------------- ts/state/createStore.ts | 4 +- ts/state/ducks/conversations.ts | 3 +- ts/state/selectors/conversations.ts | 62 ++++++++----- 7 files changed, 84 insertions(+), 165 deletions(-) delete mode 100644 ts/components/session/conversation/SessionMessagesTypes.tsx diff --git a/main.js b/main.js index 841e9029c..40e6aa2c8 100644 --- a/main.js +++ b/main.js @@ -348,7 +348,9 @@ async function createWindow() { if (config.get('openDevTools')) { // Open the DevTools. - mainWindow.webContents.openDevTools(); + mainWindow.webContents.openDevTools({ + mode: 'bottom', + }); } captureClicks(mainWindow); diff --git a/ts/components/session/SessionSearchInput.tsx b/ts/components/session/SessionSearchInput.tsx index ef5dec91b..a7d3ebfe3 100644 --- a/ts/components/session/SessionSearchInput.tsx +++ b/ts/components/session/SessionSearchInput.tsx @@ -3,11 +3,11 @@ import { useSelector } from 'react-redux'; import { getConversationsCount } from '../../state/selectors/conversations'; import { SessionIconButton, SessionIconSize, SessionIconType } from './icon'; -interface Props { +type Props = { searchString: string; onChange: any; placeholder: string; -} +}; export const SessionSearchInput = (props: Props) => { const { searchString, onChange, placeholder } = props; diff --git a/ts/components/session/conversation/SessionMessagesList.tsx b/ts/components/session/conversation/SessionMessagesList.tsx index 7ec79af26..5e4d1bab5 100644 --- a/ts/components/session/conversation/SessionMessagesList.tsx +++ b/ts/components/session/conversation/SessionMessagesList.tsx @@ -1,14 +1,18 @@ import React from 'react'; import { useSelector } from 'react-redux'; -import { QuoteClickOptions } from '../../../models/messageType'; -import { getSortedMessagesTypesOfSelectedConversation } from '../../../state/selectors/conversations'; +import { PropsForDataExtractionNotification, QuoteClickOptions } from '../../../models/messageType'; import { - DataExtractionNotificationItem, - GenericMessageItem, - GroupInvitationItem, - GroupUpdateItem, - TimerNotificationItem, -} from './SessionMessagesTypes'; + PropsForExpirationTimer, + PropsForGroupInvitation, + PropsForGroupUpdate, +} from '../../../state/ducks/conversations'; +import { getSortedMessagesTypesOfSelectedConversation } from '../../../state/selectors/conversations'; +import { DataExtractionNotification } from '../../conversation/DataExtractionNotification'; +import { GroupInvitation } from '../../conversation/GroupInvitation'; +import { GroupNotification } from '../../conversation/GroupNotification'; +import { Message } from '../../conversation/Message'; +import { TimerNotification } from '../../conversation/TimerNotification'; +import { SessionLastSeenIndicator } from './SessionLastSeenIndicator'; export const SessionMessagesList = (props: { scrollToQuoteMessage: (options: QuoteClickOptions) => Promise; @@ -18,55 +22,44 @@ export const SessionMessagesList = (props: { return ( <> {messagesProps.map(messageProps => { - if (messageProps.messageType === 'group-notification') { - return ( - - ); + const messageId = messageProps.message.props.messageId; + const unreadIndicator = messageProps.showUnreadIndicator ? ( + + ) : null; + if (messageProps.message?.messageType === 'group-notification') { + const msgProps = messageProps.message.props as PropsForGroupUpdate; + return [, unreadIndicator]; } - if (messageProps.messageType === 'group-invitation') { - return ( - - ); + if (messageProps.message?.messageType === 'group-invitation') { + const msgProps = messageProps.message.props as PropsForGroupInvitation; + return [, unreadIndicator]; } - if (messageProps.messageType === 'data-extraction') { - return ( - - ); + if (messageProps.message?.messageType === 'data-extraction') { + const msgProps = messageProps.message.props as PropsForDataExtractionNotification; + + return [, unreadIndicator]; } - if (messageProps.messageType === 'timer-notification') { - return ( - - ); + if (messageProps.message?.messageType === 'timer-notification') { + const msgProps = messageProps.message.props as PropsForExpirationTimer; + + return [, unreadIndicator]; } if (!messageProps) { return null; } - // firstMessageOfSeries tells us to render the avatar only for the first message - // in a series of messages from the same user - return ( - - ); + return [ + , + unreadIndicator, + ]; })} ); diff --git a/ts/components/session/conversation/SessionMessagesTypes.tsx b/ts/components/session/conversation/SessionMessagesTypes.tsx deleted file mode 100644 index bd6c75918..000000000 --- a/ts/components/session/conversation/SessionMessagesTypes.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import React from 'react'; -import { useSelector } from 'react-redux'; -import { PropsForDataExtractionNotification, QuoteClickOptions } from '../../../models/messageType'; -import { - PropsForExpirationTimer, - PropsForGroupInvitation, - PropsForGroupUpdate, -} from '../../../state/ducks/conversations'; -import { getFirstUnreadMessageId } from '../../../state/selectors/conversations'; -import { DataExtractionNotification } from '../../conversation/DataExtractionNotification'; -import { GroupInvitation } from '../../conversation/GroupInvitation'; -import { GroupNotification } from '../../conversation/GroupNotification'; -import { Message } from '../../conversation/Message'; -import { TimerNotification } from '../../conversation/TimerNotification'; -import { SessionLastSeenIndicator } from './SessionLastSeenIndicator'; - -export const UnreadIndicator = (props: { messageId: string }) => { - const isFirstUnreadOnOpen = useSelector(getFirstUnreadMessageId); - if (!isFirstUnreadOnOpen || isFirstUnreadOnOpen !== props.messageId) { - return null; - } - return ; -}; - -export const GroupUpdateItem = (props: { groupNotificationProps: PropsForGroupUpdate }) => { - return ( - - - - - ); -}; - -export const GroupInvitationItem = (props: { - propsForGroupInvitation: PropsForGroupInvitation; -}) => { - return ( - - - - - - ); -}; - -export const DataExtractionNotificationItem = (props: { - propsForDataExtractionNotification: PropsForDataExtractionNotification; -}) => { - return ( - - - - - - ); -}; - -export const TimerNotificationItem = (props: { timerProps: PropsForExpirationTimer }) => { - return ( - - - - - - ); -}; - -export const GenericMessageItem = (props: { - messageId: string; - scrollToQuoteMessage: (options: QuoteClickOptions) => Promise; -}) => { - const messageId = props.messageId; - - return ( - - - - - ); -}; diff --git a/ts/state/createStore.ts b/ts/state/createStore.ts index 56f187006..a508ae102 100644 --- a/ts/state/createStore.ts +++ b/ts/state/createStore.ts @@ -42,7 +42,7 @@ export const createStore = (initialState: any) => preloadedState: initialState, middleware: (getDefaultMiddleware: any) => getDefaultMiddleware({ - serializableCheck: false, - immutableCheck: false, + serializableCheck: true, + immutableCheck: true, }).concat(middlewareList), }); diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 2d285c87b..170f9ebd7 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -660,9 +660,9 @@ const conversationsSlice = createSlice({ return state; } + // keep the unread visible just like in other apps. It will be shown until the user changes convo return { ...state, - firstUnreadMessageId: undefined, }; }, @@ -833,7 +833,6 @@ export async function openConversationWithMessages(args: { const initialMessages = await getMessages(conversationKey, 30); perfEnd('getMessages', 'getMessages'); - console.warn('initialMessages', initialMessages); window.inboxStore?.dispatch( actions.openConversationExternal({ diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index 25026cfa0..d801a2c7f 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -130,53 +130,74 @@ export const getSortedMessagesOfSelectedConversation = createSelector( } ); +export const getFirstUnreadMessageId = createSelector( + getConversations, + (state: ConversationsStateType): string | undefined => { + return state.firstUnreadMessageId; + } +); + export type MessagePropsType = | 'group-notification' | 'group-invitation' | 'data-extraction' | 'timer-notification' - | 'regular-message'; + | 'regular-message' + | 'unread-indicator'; export const getSortedMessagesTypesOfSelectedConversation = createSelector( getMessagesOfSelectedConversation, - ( - sortedMessages - ): Array<{ - messageType: MessagePropsType; - props: any; - }> => { + getFirstUnreadMessageId, + (sortedMessages, firstUnreadId) => { return sortedMessages.map(msg => { + const isFirstUnread = Boolean(firstUnreadId === msg.propsForMessage.id); + if (msg.propsForDataExtractionNotification) { return { - messageType: 'data-extraction', - props: { ...msg.propsForDataExtractionNotification, messageId: msg.propsForMessage.id }, + showUnreadIndicator: isFirstUnread, + message: { + messageType: 'data-extraction', + props: { ...msg.propsForDataExtractionNotification, messageId: msg.propsForMessage.id }, + }, }; } if (msg.propsForGroupInvitation) { return { - messageType: 'group-invitation', - props: { ...msg.propsForGroupInvitation, messageId: msg.propsForMessage.id }, + showUnreadIndicator: isFirstUnread, + message: { + messageType: 'group-invitation', + props: { ...msg.propsForGroupInvitation, messageId: msg.propsForMessage.id }, + }, }; } if (msg.propsForGroupNotification) { return { - messageType: 'group-notification', - props: { ...msg.propsForGroupNotification, messageId: msg.propsForMessage.id }, + showUnreadIndicator: isFirstUnread, + message: { + messageType: 'group-notification', + props: { ...msg.propsForGroupNotification, messageId: msg.propsForMessage.id }, + }, }; } if (msg.propsForTimerNotification) { return { - messageType: 'data-extraction', - props: { ...msg.propsForTimerNotification, messageId: msg.propsForMessage.id }, + showUnreadIndicator: isFirstUnread, + message: { + messageType: 'timer-notification', + props: { ...msg.propsForTimerNotification, messageId: msg.propsForMessage.id }, + }, }; } return { - messageType: 'regular-message', - props: { messageId: msg.propsForMessage.id }, + showUnreadIndicator: isFirstUnread, + message: { + messageType: 'regular-message', + props: { messageId: msg.propsForMessage.id }, + }, }; }); } @@ -538,13 +559,6 @@ function sortMessages( return messagesSorted; } -export const getFirstUnreadMessageId = createSelector( - getConversations, - (state: ConversationsStateType): string | undefined => { - return state.firstUnreadMessageId; - } -); - export const getMostRecentMessageId = createSelector( getSortedMessagesOfSelectedConversation, (messages: Array): string | undefined => {