blob: 66915abb612db831c96bdc4c5510c1d2daec8542 [file] [log] [blame]
/*
* Copyright (C) 2022 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
import { Typography } from '@mui/material';
import { Box, Stack } from '@mui/system';
import { Message } from 'jami-web-common';
import { MutableRefObject, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Waypoint } from 'react-waypoint';
import { useAuthContext } from '../contexts/AuthProvider';
import { useConversationContext } from '../contexts/ConversationProvider';
import { MessageRow } from './Message';
import { ArrowDownIcon } from './SvgIcon';
interface MessageListProps {
messages: Message[];
}
export default function MessageList({ messages }: MessageListProps) {
const { account } = useAuthContext();
const { members } = useConversationContext();
const [showScrollButton, setShowScrollButton] = useState(false);
const listBottomRef = useRef<HTMLElement>();
return (
<>
<Stack flex={1} overflow="auto" padding="0px 16px" direction="column-reverse">
{/* Here is the bottom of the list of messages because of 'column-reverse' */}
<Box ref={listBottomRef} />
<Waypoint
onEnter={() => setShowScrollButton(false)}
onLeave={() => setShowScrollButton(true)}
bottomOffset="-100px"
/>
<Stack direction="column-reverse">
{
// most recent messages first
messages.map((message, index) => {
const isAccountMessage = message.author === account.getUri();
let author;
if (isAccountMessage) {
author = account;
} else {
const member = members.find((member) => message.author === member.contact.uri);
author = member?.contact;
}
if (!author) {
return null;
}
const props = {
messageIndex: index,
messages,
isAccountMessage,
author,
};
return <MessageRow key={message.id} {...props} />;
})
}
</Stack>
<Waypoint onEnter={() => console.log('should load more messages')} topOffset="-200px" />
</Stack>
{showScrollButton && (
<Box position="relative">
<Box position="absolute" bottom="10px" left="50%" sx={{ transform: 'translate(-50%)' }}>
<ScrollToEndButton listBottomRef={listBottomRef} />
</Box>
</Box>
)}
</>
);
}
interface ScrollToEndButtonProps {
listBottomRef: MutableRefObject<HTMLElement | undefined>;
}
const ScrollToEndButton = ({ listBottomRef }: ScrollToEndButtonProps) => {
const { t } = useTranslation();
const textColor = 'white';
return (
<Stack
direction="row"
borderRadius="5px"
height="30px"
alignItems="center"
padding="0 16px"
spacing="12px"
sx={{
backgroundColor: '#005699', // Should be same color as message bubble
cursor: 'pointer',
}}
onClick={() => listBottomRef.current?.scrollIntoView({ behavior: 'smooth' })}
>
<ArrowDownIcon sx={{ fontSize: '12px', color: textColor }} />
<Typography variant="caption" fontWeight="bold" color={textColor}>
{t('messages_scroll_to_end')}
</Typography>
</Stack>
);
};