bigbuffet-rw/app/soapbox/features/chats/components/chat-list-item.tsx

149 lines
5.2 KiB
TypeScript
Raw Normal View History

2022-09-23 06:04:01 -07:00
import React, { useMemo } from 'react';
import { defineMessages, useIntl } from 'react-intl';
2022-09-12 13:46:19 -07:00
2022-09-23 06:04:01 -07:00
import { openModal } from 'soapbox/actions/modals';
2022-09-12 13:46:19 -07:00
import RelativeTimestamp from 'soapbox/components/relative-timestamp';
2022-09-23 06:07:22 -07:00
import { Avatar, HStack, Icon, Stack, Text } from 'soapbox/components/ui';
2022-09-12 13:46:19 -07:00
import VerificationBadge from 'soapbox/components/verification_badge';
2022-09-23 06:04:01 -07:00
import DropdownMenuContainer from 'soapbox/containers/dropdown_menu_container';
import { useAppDispatch } from 'soapbox/hooks';
2022-09-23 06:07:22 -07:00
import { IChat, IChatSilence, useChat, useChatSilence } from 'soapbox/queries/chats';
2022-09-12 13:46:19 -07:00
2022-09-23 06:04:01 -07:00
import type { Menu } from 'soapbox/components/dropdown_menu';
const messages = defineMessages({
2022-09-23 06:07:22 -07:00
silenceNotifications: { id: 'chat_settings.silence_notifications', defaultMessage: 'Silence notifications' },
unsilenceNotifications: { id: 'chat_settings.unsilence_notifications', defaultMessage: 'Unsilence notifications' },
2022-09-23 06:04:01 -07:00
leaveMessage: { id: 'chat_settings.leave.message', defaultMessage: 'Are you sure you want to leave this chat? This conversation will be removed from your inbox.' },
leaveHeading: { id: 'chat_settings.leave.heading', defaultMessage: 'Leave Chat' },
leaveConfirm: { id: 'chat_settings.leave.confirm', defaultMessage: 'Leave Chat' },
leaveChat: { id: 'chat_settings.options.leave_chat', defaultMessage: 'Leave Chat' },
});
2022-09-12 13:46:19 -07:00
interface IChatListItemInterface {
chat: IChat,
onClick: (chat: any) => void,
2022-09-16 05:57:09 -07:00
chatSilence?: IChatSilence
2022-09-12 13:46:19 -07:00
}
2022-09-16 05:57:09 -07:00
const ChatListItem: React.FC<IChatListItemInterface> = ({ chat, chatSilence, onClick }) => {
2022-09-23 06:04:01 -07:00
const dispatch = useAppDispatch();
const intl = useIntl();
const { handleSilence } = useChatSilence(chat);
const { deleteChat } = useChat(chat?.id as string);
const menu = useMemo((): Menu => {
const menu: Menu = [];
if (chatSilence) {
menu.push({
2022-09-23 06:07:22 -07:00
text: intl.formatMessage(messages.unsilenceNotifications),
2022-09-23 06:04:01 -07:00
action: (event) => {
event.stopPropagation();
handleSilence();
},
icon: require('@tabler/icons/bell.svg'),
});
} else {
menu.push({
2022-09-23 06:07:22 -07:00
text: intl.formatMessage(messages.silenceNotifications),
2022-09-23 06:04:01 -07:00
action: (event) => {
event.stopPropagation();
handleSilence();
},
icon: require('@tabler/icons/bell-off.svg'),
});
}
menu.push({
text: intl.formatMessage(messages.leaveChat),
action: (event) => {
event.stopPropagation();
dispatch(openModal('CONFIRM', {
heading: intl.formatMessage(messages.leaveHeading),
message: intl.formatMessage(messages.leaveMessage),
confirm: intl.formatMessage(messages.leaveConfirm),
confirmationTheme: 'primary',
onConfirm: () => deleteChat.mutate(),
}));
},
icon: require('@tabler/icons/logout.svg'),
});
return menu;
}, [chatSilence]);
2022-09-12 13:46:19 -07:00
return (
<button
key={chat.id}
type='button'
onClick={() => onClick(chat)}
2022-09-23 06:04:01 -07:00
className='group px-2 py-3 w-full flex flex-col rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 focus:shadow-inset-ring'
2022-09-12 13:46:19 -07:00
data-testid='chat'
>
<HStack alignItems='center' justifyContent='between' space={2} className='w-full'>
<HStack alignItems='center' space={2} className='overflow-hidden'>
<Avatar src={chat.account?.avatar} size={40} className='flex-none' />
<Stack alignItems='start' className='overflow-hidden'>
<div className='flex items-center space-x-1 flex-grow w-full'>
<Text weight='bold' size='sm' align='left' truncate>{chat.account?.display_name || `@${chat.account.username}`}</Text>
{chat.account?.verified && <VerificationBadge />}
</div>
{chat.last_message?.content && (
<Text
align='left'
size='sm'
weight='medium'
theme={chat.last_message.unread ? 'default' : 'muted'}
2022-09-12 13:46:19 -07:00
truncate
className='w-full h-5 truncate-child pointer-events-none'
2022-09-12 13:46:19 -07:00
data-testid='chat-last-message'
dangerouslySetInnerHTML={{ __html: chat.last_message?.content }}
/>
)}
</Stack>
</HStack>
2022-09-16 05:57:09 -07:00
<HStack alignItems='center' space={2}>
2022-09-23 06:04:01 -07:00
<div className='text-gray-600 hidden group-hover:block hover:text-gray-100'>
<DropdownMenuContainer
items={menu}
src={require('@tabler/icons/dots.svg')}
title='Settings'
/>
</div>
2022-09-16 05:57:09 -07:00
{chatSilence ? (
<Icon src={require('@tabler/icons/bell-off.svg')} className='w-5 h-5 text-gray-600' />
) : null}
{chat.last_message && (
<>
{chat.last_message.unread && (
<div
className='w-2 h-2 rounded-full bg-secondary-500'
data-testid='chat-unread-indicator'
/>
)}
2022-09-12 13:46:19 -07:00
2022-09-16 05:57:09 -07:00
<RelativeTimestamp
timestamp={chat.last_message.created_at}
align='right'
size='xs'
truncate
/>
</>
)}
</HStack>
2022-09-12 13:46:19 -07:00
</HStack>
</button>
);
};
export default ChatListItem;