moved the unread indicator to outside of message items

pull/1884/head
audric 4 years ago
parent 985a5d92bc
commit 40566a58a4

@ -348,7 +348,9 @@ async function createWindow() {
if (config.get('openDevTools')) { if (config.get('openDevTools')) {
// Open the DevTools. // Open the DevTools.
mainWindow.webContents.openDevTools(); mainWindow.webContents.openDevTools({
mode: 'bottom',
});
} }
captureClicks(mainWindow); captureClicks(mainWindow);

@ -3,11 +3,11 @@ import { useSelector } from 'react-redux';
import { getConversationsCount } from '../../state/selectors/conversations'; import { getConversationsCount } from '../../state/selectors/conversations';
import { SessionIconButton, SessionIconSize, SessionIconType } from './icon'; import { SessionIconButton, SessionIconSize, SessionIconType } from './icon';
interface Props { type Props = {
searchString: string; searchString: string;
onChange: any; onChange: any;
placeholder: string; placeholder: string;
} };
export const SessionSearchInput = (props: Props) => { export const SessionSearchInput = (props: Props) => {
const { searchString, onChange, placeholder } = props; const { searchString, onChange, placeholder } = props;

@ -1,14 +1,18 @@
import React from 'react'; import React from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { QuoteClickOptions } from '../../../models/messageType'; import { PropsForDataExtractionNotification, QuoteClickOptions } from '../../../models/messageType';
import { getSortedMessagesTypesOfSelectedConversation } from '../../../state/selectors/conversations';
import { import {
DataExtractionNotificationItem, PropsForExpirationTimer,
GenericMessageItem, PropsForGroupInvitation,
GroupInvitationItem, PropsForGroupUpdate,
GroupUpdateItem, } from '../../../state/ducks/conversations';
TimerNotificationItem, import { getSortedMessagesTypesOfSelectedConversation } from '../../../state/selectors/conversations';
} from './SessionMessagesTypes'; 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: { export const SessionMessagesList = (props: {
scrollToQuoteMessage: (options: QuoteClickOptions) => Promise<void>; scrollToQuoteMessage: (options: QuoteClickOptions) => Promise<void>;
@ -18,55 +22,44 @@ export const SessionMessagesList = (props: {
return ( return (
<> <>
{messagesProps.map(messageProps => { {messagesProps.map(messageProps => {
if (messageProps.messageType === 'group-notification') { const messageId = messageProps.message.props.messageId;
return ( const unreadIndicator = messageProps.showUnreadIndicator ? (
<GroupUpdateItem <SessionLastSeenIndicator key={`unread-indicator-${messageId}`} />
key={messageProps.props.messageId} ) : null;
groupNotificationProps={messageProps.props} if (messageProps.message?.messageType === 'group-notification') {
/> const msgProps = messageProps.message.props as PropsForGroupUpdate;
); return [<GroupNotification key={messageId} {...msgProps} />, unreadIndicator];
} }
if (messageProps.messageType === 'group-invitation') { if (messageProps.message?.messageType === 'group-invitation') {
return ( const msgProps = messageProps.message.props as PropsForGroupInvitation;
<GroupInvitationItem return [<GroupInvitation key={messageId} {...msgProps} />, unreadIndicator];
key={messageProps.props.messageId}
propsForGroupInvitation={messageProps.props}
/>
);
} }
if (messageProps.messageType === 'data-extraction') { if (messageProps.message?.messageType === 'data-extraction') {
return ( const msgProps = messageProps.message.props as PropsForDataExtractionNotification;
<DataExtractionNotificationItem
key={messageProps.props.messageId} return [<DataExtractionNotification key={messageId} {...msgProps} />, unreadIndicator];
propsForDataExtractionNotification={messageProps.props}
/>
);
} }
if (messageProps.messageType === 'timer-notification') { if (messageProps.message?.messageType === 'timer-notification') {
return ( const msgProps = messageProps.message.props as PropsForExpirationTimer;
<TimerNotificationItem
key={messageProps.props.messageId} return [<TimerNotification key={messageId} {...msgProps} />, unreadIndicator];
timerProps={messageProps.props}
/>
);
} }
if (!messageProps) { if (!messageProps) {
return null; return null;
} }
// firstMessageOfSeries tells us to render the avatar only for the first message return [
// in a series of messages from the same user <Message
return ( messageId={messageId}
<GenericMessageItem onQuoteClick={props.scrollToQuoteMessage}
key={messageProps.props.messageId} key={messageId}
messageId={messageProps.props.messageId} />,
scrollToQuoteMessage={props.scrollToQuoteMessage} unreadIndicator,
/> ];
);
})} })}
</> </>
); );

@ -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 <SessionLastSeenIndicator key={`unread-indicator-${props.messageId}`} />;
};
export const GroupUpdateItem = (props: { groupNotificationProps: PropsForGroupUpdate }) => {
return (
<React.Fragment key={props.groupNotificationProps.messageId}>
<GroupNotification
key={props.groupNotificationProps.messageId}
{...props.groupNotificationProps}
/>
<UnreadIndicator messageId={props.groupNotificationProps.messageId} />
</React.Fragment>
);
};
export const GroupInvitationItem = (props: {
propsForGroupInvitation: PropsForGroupInvitation;
}) => {
return (
<React.Fragment key={props.propsForGroupInvitation.messageId}>
<GroupInvitation
key={props.propsForGroupInvitation.messageId}
{...props.propsForGroupInvitation}
/>
<UnreadIndicator messageId={props.propsForGroupInvitation.messageId} />
</React.Fragment>
);
};
export const DataExtractionNotificationItem = (props: {
propsForDataExtractionNotification: PropsForDataExtractionNotification;
}) => {
return (
<React.Fragment key={props.propsForDataExtractionNotification.messageId}>
<DataExtractionNotification
key={props.propsForDataExtractionNotification.messageId}
{...props.propsForDataExtractionNotification}
/>
<UnreadIndicator messageId={props.propsForDataExtractionNotification.messageId} />
</React.Fragment>
);
};
export const TimerNotificationItem = (props: { timerProps: PropsForExpirationTimer }) => {
return (
<React.Fragment key={props.timerProps.messageId}>
<TimerNotification key={props.timerProps.messageId} {...props.timerProps} />
<UnreadIndicator messageId={props.timerProps.messageId} />
</React.Fragment>
);
};
export const GenericMessageItem = (props: {
messageId: string;
scrollToQuoteMessage: (options: QuoteClickOptions) => Promise<void>;
}) => {
const messageId = props.messageId;
return (
<React.Fragment key={messageId}>
<Message messageId={messageId} onQuoteClick={props.scrollToQuoteMessage} key={messageId} />
<UnreadIndicator messageId={messageId} />
</React.Fragment>
);
};

@ -42,7 +42,7 @@ export const createStore = (initialState: any) =>
preloadedState: initialState, preloadedState: initialState,
middleware: (getDefaultMiddleware: any) => middleware: (getDefaultMiddleware: any) =>
getDefaultMiddleware({ getDefaultMiddleware({
serializableCheck: false, serializableCheck: true,
immutableCheck: false, immutableCheck: true,
}).concat(middlewareList), }).concat(middlewareList),
}); });

@ -660,9 +660,9 @@ const conversationsSlice = createSlice({
return state; return state;
} }
// keep the unread visible just like in other apps. It will be shown until the user changes convo
return { return {
...state, ...state,
firstUnreadMessageId: undefined,
}; };
}, },
@ -833,7 +833,6 @@ export async function openConversationWithMessages(args: {
const initialMessages = await getMessages(conversationKey, 30); const initialMessages = await getMessages(conversationKey, 30);
perfEnd('getMessages', 'getMessages'); perfEnd('getMessages', 'getMessages');
console.warn('initialMessages', initialMessages);
window.inboxStore?.dispatch( window.inboxStore?.dispatch(
actions.openConversationExternal({ actions.openConversationExternal({

@ -130,53 +130,74 @@ export const getSortedMessagesOfSelectedConversation = createSelector(
} }
); );
export const getFirstUnreadMessageId = createSelector(
getConversations,
(state: ConversationsStateType): string | undefined => {
return state.firstUnreadMessageId;
}
);
export type MessagePropsType = export type MessagePropsType =
| 'group-notification' | 'group-notification'
| 'group-invitation' | 'group-invitation'
| 'data-extraction' | 'data-extraction'
| 'timer-notification' | 'timer-notification'
| 'regular-message'; | 'regular-message'
| 'unread-indicator';
export const getSortedMessagesTypesOfSelectedConversation = createSelector( export const getSortedMessagesTypesOfSelectedConversation = createSelector(
getMessagesOfSelectedConversation, getMessagesOfSelectedConversation,
( getFirstUnreadMessageId,
sortedMessages (sortedMessages, firstUnreadId) => {
): Array<{
messageType: MessagePropsType;
props: any;
}> => {
return sortedMessages.map(msg => { return sortedMessages.map(msg => {
const isFirstUnread = Boolean(firstUnreadId === msg.propsForMessage.id);
if (msg.propsForDataExtractionNotification) { if (msg.propsForDataExtractionNotification) {
return { return {
messageType: 'data-extraction', showUnreadIndicator: isFirstUnread,
props: { ...msg.propsForDataExtractionNotification, messageId: msg.propsForMessage.id }, message: {
messageType: 'data-extraction',
props: { ...msg.propsForDataExtractionNotification, messageId: msg.propsForMessage.id },
},
}; };
} }
if (msg.propsForGroupInvitation) { if (msg.propsForGroupInvitation) {
return { return {
messageType: 'group-invitation', showUnreadIndicator: isFirstUnread,
props: { ...msg.propsForGroupInvitation, messageId: msg.propsForMessage.id }, message: {
messageType: 'group-invitation',
props: { ...msg.propsForGroupInvitation, messageId: msg.propsForMessage.id },
},
}; };
} }
if (msg.propsForGroupNotification) { if (msg.propsForGroupNotification) {
return { return {
messageType: 'group-notification', showUnreadIndicator: isFirstUnread,
props: { ...msg.propsForGroupNotification, messageId: msg.propsForMessage.id }, message: {
messageType: 'group-notification',
props: { ...msg.propsForGroupNotification, messageId: msg.propsForMessage.id },
},
}; };
} }
if (msg.propsForTimerNotification) { if (msg.propsForTimerNotification) {
return { return {
messageType: 'data-extraction', showUnreadIndicator: isFirstUnread,
props: { ...msg.propsForTimerNotification, messageId: msg.propsForMessage.id }, message: {
messageType: 'timer-notification',
props: { ...msg.propsForTimerNotification, messageId: msg.propsForMessage.id },
},
}; };
} }
return { return {
messageType: 'regular-message', showUnreadIndicator: isFirstUnread,
props: { messageId: msg.propsForMessage.id }, message: {
messageType: 'regular-message',
props: { messageId: msg.propsForMessage.id },
},
}; };
}); });
} }
@ -538,13 +559,6 @@ function sortMessages(
return messagesSorted; return messagesSorted;
} }
export const getFirstUnreadMessageId = createSelector(
getConversations,
(state: ConversationsStateType): string | undefined => {
return state.firstUnreadMessageId;
}
);
export const getMostRecentMessageId = createSelector( export const getMostRecentMessageId = createSelector(
getSortedMessagesOfSelectedConversation, getSortedMessagesOfSelectedConversation,
(messages: Array<MessageModelPropsWithoutConvoProps>): string | undefined => { (messages: Array<MessageModelPropsWithoutConvoProps>): string | undefined => {

Loading…
Cancel
Save