fix position of unread banner on conversation (search for first read)

pull/1387/head
Audric Ackermann 5 years ago
parent 48ecb8fc4b
commit 3d11271471
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -154,7 +154,6 @@ export class SessionConversation extends React.Component<Props, State> {
public async componentWillMount() { public async componentWillMount() {
await this.loadInitialMessages(); await this.loadInitialMessages();
this.setState({ initialFetchComplete: true });
} }
public componentWillUnmount() { public componentWillUnmount() {
@ -331,15 +330,20 @@ export class SessionConversation extends React.Component<Props, State> {
// After the inital fetch, all new messages are automatically added from onNewMessage // After the inital fetch, all new messages are automatically added from onNewMessage
// in the conversation model. // in the conversation model.
// The only time we need to call getMessages() is to grab more messages on scroll. // The only time we need to call getMessages() is to grab more messages on scroll.
const { initialFetchComplete } = this.state; if (this.state.initialFetchComplete) {
if (initialFetchComplete) {
return; return;
} }
return this.getMessages(Constants.CONVERSATION.DEFAULT_MESSAGE_FETCH_COUNT); return this.getMessages(
Constants.CONVERSATION.DEFAULT_MESSAGE_FETCH_COUNT,
() => {
this.setState({ initialFetchComplete: true });
}
);
} }
public async getMessages(numMessages?: number) { // tslint:disable-next-line: no-empty
public async getMessages(numMessages?: number, callback: any = () => {}) {
const { unreadCount } = this.state; const { unreadCount } = this.state;
const { conversationKey } = this.props; const { conversationKey } = this.props;
let msgCount = let msgCount =
@ -365,7 +369,7 @@ export class SessionConversation extends React.Component<Props, State> {
const messages = []; const messages = [];
// no need to do that `firstMessageOfSeries` on a private chat // no need to do that `firstMessageOfSeries` on a private chat
if (this.props.conversation.type === 'direct') { if (this.props.conversation.type === 'direct') {
this.setState({ messages: messageSet.models }); this.setState({ messages: messageSet.models }, callback);
return; return;
} }
@ -386,7 +390,7 @@ export class SessionConversation extends React.Component<Props, State> {
messages.push({ ...messageModels[i], firstMessageOfSeries }); messages.push({ ...messageModels[i], firstMessageOfSeries });
} }
this.setState({ messages }); this.setState({ messages }, callback);
} }
public getHeaderProps() { public getHeaderProps() {
@ -494,19 +498,13 @@ export class SessionConversation extends React.Component<Props, State> {
public getMessagesListProps() { public getMessagesListProps() {
const { conversation } = this.props; const { conversation } = this.props;
const { const { messages, quotedMessageTimestamp, selectedMessages } = this.state;
messages,
initialFetchComplete,
quotedMessageTimestamp,
selectedMessages,
} = this.state;
return { return {
selectedMessages, selectedMessages,
conversationKey: conversation.id, conversationKey: conversation.id,
messages, messages,
resetSelection: this.resetSelection, resetSelection: this.resetSelection,
initialFetchComplete,
quotedMessageTimestamp, quotedMessageTimestamp,
conversation, conversation,
selectMessage: this.selectMessage, selectMessage: this.selectMessage,

@ -27,7 +27,6 @@ interface Props {
selectedMessages: Array<string>; selectedMessages: Array<string>;
conversationKey: string; conversationKey: string;
messages: Array<MessageModel>; messages: Array<MessageModel>;
initialFetchComplete: boolean;
conversation: ConversationType; conversation: ConversationType;
messageContainerRef: React.RefObject<any>; messageContainerRef: React.RefObject<any>;
selectMessage: (messageId: string) => void; selectMessage: (messageId: string) => void;
@ -116,12 +115,16 @@ export class SessionConversationMessagesList extends React.Component<
} }
public renderMessages(messages: Array<MessageModel>) { public renderMessages(messages: Array<MessageModel>) {
const { conversation } = this.props;
const { isScrolledToBottom } = this.state; const { isScrolledToBottom } = this.state;
const { unreadCount } = conversation;
const multiSelectMode = Boolean(this.props.selectedMessages.length); const multiSelectMode = Boolean(this.props.selectedMessages.length);
let currentMessageIndex = 0; let currentMessageIndex = 0;
// find the first unread message in the list of messages. We use this to display the
// unread banner so this is at all times at the correct index.
const findFirstUnreadIndex = messages.findIndex(
message =>
!(message?.attributes?.unread && message?.attributes?.unread !== false)
);
return ( return (
<> <>
{messages.map((message: MessageModel) => { {messages.map((message: MessageModel) => {
@ -134,16 +137,18 @@ export class SessionConversationMessagesList extends React.Component<
const propsForGroupInvitation = message.propsForGroupInvitation; const propsForGroupInvitation = message.propsForGroupInvitation;
const groupNotificationProps = message.propsForGroupNotification; const groupNotificationProps = message.propsForGroupNotification;
let unreadIndicator = null;
// if there are some unread messages
// if there is some unread messages const showUnreadIndicator =
if ( !isScrolledToBottom &&
unreadCount > 0 && findFirstUnreadIndex > 0 &&
currentMessageIndex === unreadCount && currentMessageIndex === findFirstUnreadIndex;
!isScrolledToBottom const unreadIndicator = (
) { <SessionLastSeenIndicator
unreadIndicator = <SessionLastSeenIndicator count={unreadCount} />; count={findFirstUnreadIndex} // count is used for the 118n of the string
} show={showUnreadIndicator}
/>
);
currentMessageIndex = currentMessageIndex + 1; currentMessageIndex = currentMessageIndex + 1;
@ -391,6 +396,15 @@ export class SessionConversationMessagesList extends React.Component<
if (scrollOffsetPc === 0 && this.state.doneInitialScroll) { if (scrollOffsetPc === 0 && this.state.doneInitialScroll) {
this.setState({ isScrolledToBottom: true }); this.setState({ isScrolledToBottom: true });
} else if (
scrollHeight !== 0 &&
scrollHeight === clientHeight &&
!this.state.isScrolledToBottom
) {
this.setState({ isScrolledToBottom: true }, () => {
// Mark messages read
this.updateReadMessages();
});
} }
} }

@ -1,11 +1,17 @@
import React from 'react'; import React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
const LastSeenBarContainer = styled.div` interface LastSeenProps {
padding-top: 25px; show: boolean;
padding-bottom: 35px; }
const LastSeenBarContainer = styled.div<LastSeenProps>`
padding-bottom: ${props => (props.show ? '35px' : 0)};
margin-inline-start: 28px; margin-inline-start: 28px;
padding-top: 28px; padding-top: ${props => (props.show ? '28px' : 0)};
transition: ${props => props.theme.common.animations.defaultDuration};
overflow: hidden;
height: ${props => (props.show ? 'auto' : 0)};
`; `;
const LastSeenBar = styled.div` const LastSeenBar = styled.div`
@ -25,12 +31,18 @@ const LastSeenText = styled.div`
color: ${props => props.theme.colors.lastSeenIndicatorTextColor}; color: ${props => props.theme.colors.lastSeenIndicatorTextColor};
`; `;
export const SessionLastSeenIndicator = ({ count }: { count: number }) => { export const SessionLastSeenIndicator = ({
count,
show,
}: {
count: number;
show: boolean;
}) => {
const { i18n } = window; const { i18n } = window;
const text = const text =
count > 1 ? i18n('unreadMessages', count) : i18n('unreadMessage', count); count > 1 ? i18n('unreadMessages', count) : i18n('unreadMessage', count);
return ( return (
<LastSeenBarContainer> <LastSeenBarContainer show={show}>
<LastSeenBar> <LastSeenBar>
<LastSeenText>{text}</LastSeenText> <LastSeenText>{text}</LastSeenText>
</LastSeenBar> </LastSeenBar>

Loading…
Cancel
Save