Improve styles for ConversationListItem
- Display last message
- Fix user talking to themself
Change-Id: Ia5bb3f9cd86a389f94bbfb3e279e7a82878f98ed
diff --git a/client/src/components/ConversationListItem.tsx b/client/src/components/ConversationListItem.tsx
index 710fe0b..985ee2c 100644
--- a/client/src/components/ConversationListItem.tsx
+++ b/client/src/components/ConversationListItem.tsx
@@ -15,7 +15,8 @@
* License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
-import { Box, ListItem, ListItemAvatar, ListItemText } from '@mui/material';
+import { Box, ListItemButton, Stack, Typography } from '@mui/material';
+import dayjs from 'dayjs';
import { IConversationSummary } from 'jami-web-common';
import { QRCodeCanvas } from 'qrcode.react';
import { useCallback, useContext, useMemo, useState } from 'react';
@@ -29,6 +30,8 @@
import { setRefreshFromSlice } from '../redux/appSlice';
import { useAppDispatch } from '../redux/hooks';
import { ConversationRouteParams } from '../router';
+import { getMessageCallText, getMessageMemberText } from '../utils/chatmessages';
+import { formatRelativeDate, formatTime } from '../utils/dates×';
import ContextMenu, { ContextMenuHandler, useContextMenuHandler } from './ContextMenu';
import ConversationAvatar from './ConversationAvatar';
import { ConfirmationDialog, DialogContentList, InfosDialog, useDialogHandler } from './Dialog';
@@ -40,13 +43,14 @@
};
export default function ConversationListItem({ conversationSummary }: ConversationListItemProps) {
+ const { account } = useAuthContext();
const {
urlParams: { conversationId: selectedConversationId },
} = useUrlParams<ConversationRouteParams>();
const contextMenuHandler = useContextMenuHandler();
const callContext = useCallContext(true);
const { callData } = useContext(CallManagerContext);
- const { t } = useTranslation();
+ const { t, i18n } = useTranslation();
const navigate = useNavigate();
const conversationId = conversationSummary.id;
@@ -58,9 +62,41 @@
}
}, [navigate, conversationId]);
- const secondaryText = useMemo(() => {
+ const timeIndicator = useMemo(() => {
+ const message = conversationSummary.lastMessage;
+ const time = dayjs.unix(Number(message.timestamp));
+ if (time.isToday()) {
+ return formatTime(time, i18n);
+ } else {
+ return formatRelativeDate(time, i18n);
+ }
+ }, [conversationSummary, i18n]);
+
+ const lastMessageText = useMemo(() => {
if (!callContext || !callData || callData.conversationId !== conversationSummary.id) {
- return conversationSummary.lastMessage.body;
+ const message = conversationSummary.lastMessage;
+ switch (message.type) {
+ case 'initial': {
+ return t('message_swarm_created');
+ }
+ case 'application/data-transfer+json': {
+ return message.fileId;
+ }
+ case 'application/call-history+json': {
+ const isAccountMessage = message.author === account.getUri();
+ return getMessageCallText(isAccountMessage, message, i18n);
+ }
+ case 'member': {
+ return getMessageMemberText(message, i18n);
+ }
+ case 'text/plain': {
+ return message.body;
+ }
+ default: {
+ console.error(`${ConversationListItem.name} received an unexpected lastMessage type: ${message.type}`);
+ return '';
+ }
+ }
}
if (callContext.callStatus === CallStatus.InCall) {
@@ -72,11 +108,11 @@
}
return callContext.callRole === 'caller' ? t('outgoing_call') : t('incoming_call');
- }, [conversationSummary, callContext, callData, t]);
+ }, [account, conversationSummary, callContext, callData, t, i18n]);
const conversationName = useMemo(
- () => conversationSummary.title ?? conversationSummary.membersNames.join(', '),
- [conversationSummary]
+ () => conversationSummary.title || conversationSummary.membersNames.join(', ') || account.getDisplayName(),
+ [account, conversationSummary]
);
return (
@@ -88,18 +124,20 @@
isSelected={isSelected}
contextMenuProps={contextMenuHandler.props}
/>
- <ListItem
- button
- alignItems="flex-start"
- selected={isSelected}
- onClick={onClick}
- onContextMenu={contextMenuHandler.handleAnchorPosition}
- >
- <ListItemAvatar>
+ <ListItemButton alignItems="flex-start" selected={isSelected} onClick={onClick}>
+ <Stack direction="row" spacing="10px">
<ConversationAvatar displayName={conversationName} />
- </ListItemAvatar>
- <ListItemText primary={conversationName} secondary={secondaryText} />
- </ListItem>
+ <Stack>
+ <Typography variant="body1">{conversationName}</Typography>
+ <Stack direction="row" spacing="5px">
+ <Typography variant="body2" fontWeight={isSelected ? 'bold' : 'normal'}>
+ {timeIndicator}
+ </Typography>
+ <Typography variant="body2">{lastMessageText}</Typography>
+ </Stack>
+ </Stack>
+ </Stack>
+ </ListItemButton>
</Box>
);
}
diff --git a/client/src/components/Message.tsx b/client/src/components/Message.tsx
index 8807295..a87d628 100644
--- a/client/src/components/Message.tsx
+++ b/client/src/components/Message.tsx
@@ -17,14 +17,15 @@
*/
import { Box, Chip, Divider, Stack, Tooltip, Typography } from '@mui/material';
import { styled } from '@mui/material/styles';
-import { Dayjs } from 'dayjs';
+import dayjs, { Dayjs } from 'dayjs';
import { Message } from 'jami-web-common';
import { ReactElement, ReactNode, useCallback, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import dayjs from '../dayjsInitializer';
import { Account } from '../models/account';
import { Contact } from '../models/contact';
+import { getMessageCallText, getMessageMemberText } from '../utils/chatmessages';
+import { formatRelativeDate, formatTime } from '../utils/dates×';
import { EmojiButton, MoreButton, ReplyMessageButton } from './Button';
import ConversationAvatar from './ConversationAvatar';
import PopoverList, { PopoverListItemData } from './PopoverList';
@@ -93,48 +94,44 @@
const MessageCall = ({ message, isAccountMessage, isFirstOfGroup, isLastOfGroup }: MessageCallProps) => {
const position = isAccountMessage ? 'end' : 'start';
- const { t } = useTranslation();
+ const { i18n } = useTranslation();
const { bubbleColor, Icon, text, textColor } = useMemo(() => {
+ const text = getMessageCallText(isAccountMessage, message, i18n);
const callDuration = dayjs.duration(parseInt(message?.duration || ''));
if (callDuration.asSeconds() === 0) {
if (isAccountMessage) {
return {
- text: t('message_call_outgoing_missed'),
+ text,
Icon: ArrowLeftCurved,
textColor: 'white',
bubbleColor: '#005699' + '80', // opacity 50%
};
} else {
return {
- text: t('message_call_incoming_missed'),
+ text,
Icon: ArrowLeftCurved,
textColor: 'black',
bubbleColor: '#C6C6C6',
};
}
} else {
- const minutes = Math.floor(callDuration.asMinutes()).toString().padStart(2, '0');
- const seconds = callDuration.format('ss');
- const interpolations = {
- duration: `${minutes}:${seconds}`,
- };
if (isAccountMessage) {
return {
- text: t('message_call_outgoing', interpolations),
+ text,
Icon: ArrowRightUp,
textColor: 'white',
bubbleColor: '#005699',
};
} else {
return {
- text: t('message_call_incoming', interpolations),
+ text,
Icon: ArrowLeftDown,
textcolor: 'black',
bubbleColor: '#E5E5E5',
};
}
}
- }, [isAccountMessage, message, t]);
+ }, [isAccountMessage, message, i18n]);
return (
<Bubble position={position} isFirstOfGroup={isFirstOfGroup} isLastOfGroup={isLastOfGroup} bubbleColor={bubbleColor}>
@@ -174,13 +171,15 @@
}
const MessageMember = ({ message }: MessageMemberProps) => {
- const { t } = useTranslation();
+ const { i18n } = useTranslation();
+
+ const text = getMessageMemberText(message, i18n);
return (
<Chip
sx={{
width: 'fit-content',
}}
- label={t('message_user_joined', { user: message.author })}
+ label={text}
/>
);
};
@@ -218,16 +217,7 @@
const DateIndicator = ({ time }: DateIndicatorProps) => {
const { i18n } = useTranslation();
-
- const textDate = useMemo(() => {
- if (time.isToday()) {
- return new Intl.RelativeTimeFormat(i18n.language, { numeric: 'auto' }).format(0, 'day');
- } else if (time.isYesterday()) {
- return new Intl.RelativeTimeFormat(i18n.language, { numeric: 'auto' }).format(-1, 'day');
- } else {
- return dayjs(time).locale(i18n.language).format('L');
- }
- }, [i18n, time]);
+ const textDate = useMemo(() => formatRelativeDate(time, i18n), [time, i18n]);
return (
<Box marginTop="30px">
@@ -267,10 +257,7 @@
const TimeIndicator = ({ time, hasDateOnTop }: TimeIndicatorProps) => {
const { i18n } = useTranslation();
-
- const textTime = useMemo(() => {
- return dayjs(time).locale(i18n.language).format('LT');
- }, [i18n, time]);
+ const textTime = useMemo(() => formatTime(time, i18n), [time, i18n]);
return (
<Stack direction="row" justifyContent="center" marginTop={hasDateOnTop ? '20px' : '30px'}>