Finish i18n for DMs
This commit is contained in:
parent
a60d6770af
commit
6240ea5a23
|
@ -17,7 +17,7 @@ const ChatListItem: React.FC<IChatListItemInterface> = ({ chat, onClick }) => {
|
|||
key={chat.id}
|
||||
type='button'
|
||||
onClick={() => onClick(chat)}
|
||||
className='px-4 py-2 w-full flex flex-col hover:bg-gray-100 dark:hover:bg-gray-800'
|
||||
className='px-4 py-2 w-full flex flex-col hover:bg-gray-100 dark:hover:bg-gray-800 focus:shadow-inset-ring'
|
||||
data-testid='chat'
|
||||
>
|
||||
<HStack alignItems='center' justifyContent='between' space={2} className='w-full'>
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
import classNames from 'clsx';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
|
||||
import { fetchChats } from 'soapbox/actions/chats';
|
||||
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
||||
import { Stack } from 'soapbox/components/ui';
|
||||
import PlaceholderChat from 'soapbox/features/placeholder/components/placeholder-chat';
|
||||
import { useAppDispatch } from 'soapbox/hooks';
|
||||
import { useChats } from 'soapbox/queries/chats';
|
||||
|
||||
import ChatListItem from './chat-list-item';
|
||||
import Blankslate from './chat-pane/blankslate';
|
||||
|
||||
interface IChatList {
|
||||
onClickChat: (chat: any) => void,
|
||||
|
@ -20,7 +19,7 @@ interface IChatList {
|
|||
}
|
||||
|
||||
const ChatList: React.FC<IChatList> = ({ onClickChat, useWindowScroll = false, searchValue, fade }) => {
|
||||
const dispatch = useDispatch();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const chatListRef = useRef(null);
|
||||
|
||||
|
@ -37,23 +36,15 @@ const ChatList: React.FC<IChatList> = ({ onClickChat, useWindowScroll = false, s
|
|||
}
|
||||
};
|
||||
|
||||
const handleRefresh = () => {
|
||||
return dispatch(fetchChats()) as any;
|
||||
};
|
||||
const handleRefresh = () => dispatch(fetchChats()) as any;
|
||||
|
||||
const renderEmpty = () => {
|
||||
if (isFetching) {
|
||||
return (
|
||||
const renderEmpty = () => (
|
||||
<Stack space={2}>
|
||||
<PlaceholderChat />
|
||||
<PlaceholderChat />
|
||||
<PlaceholderChat />
|
||||
</Stack>
|
||||
);
|
||||
} else {
|
||||
return <Blankslate />;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='relative h-full'>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import classNames from 'clsx';
|
||||
import React from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import { openModal } from 'soapbox/actions/modals';
|
||||
import { initReport } from 'soapbox/actions/reports';
|
||||
|
@ -8,21 +9,31 @@ import { useChatContext } from 'soapbox/contexts/chat-context';
|
|||
import { useAppDispatch } from 'soapbox/hooks';
|
||||
import { useChat } from 'soapbox/queries/chats';
|
||||
|
||||
const messages = defineMessages({
|
||||
leaveChatHeading: { id: 'chat_message_list_intro.leave_chat.heading', defaultMessage: 'Leave Chat' },
|
||||
leaveChatMessage: { id: 'chat_message_list_intro.leave_chat.message', defaultMessage: 'Are you sure you want to leave this chat? This conversation will be removed from your inbox.' },
|
||||
leaveChatConfirm: { id: 'chat_message_list_intro.leave_chat.confirm', defaultMessage: 'Leave Chat' },
|
||||
intro: { id: 'chat_message_list_intro.intro', defaultMessage: 'wants to start a chat with you' },
|
||||
accept: { id: 'chat_message_list_intro.actions.accept', defaultMessage: 'Accept' },
|
||||
leaveChat: { id: 'chat_message_list_intro.actions.leave_chat', defaultMessage: 'Leave chat' },
|
||||
report: { id: 'chat_message_list_intro.actions.report', defaultMessage: 'Report' },
|
||||
messageLifespan: { id: 'chat_message_list_intro.actions.message_lifespan', defaultMessage: 'Messages older than 15 days are deleted.' },
|
||||
});
|
||||
|
||||
const ChatMessageListIntro = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
|
||||
const { chat, needsAcceptance } = useChatContext();
|
||||
const { acceptChat, deleteChat } = useChat(chat?.id as string);
|
||||
|
||||
const handleLeaveChat = () => {
|
||||
dispatch(openModal('CONFIRM', {
|
||||
heading: 'Leave Chat',
|
||||
message: 'Are you sure you want to leave this chat? This conversation will be removed from your inbox.',
|
||||
confirm: 'Leave Chat',
|
||||
heading: intl.formatMessage(messages.leaveChatHeading),
|
||||
message: intl.formatMessage(messages.leaveChatMessage),
|
||||
confirm: intl.formatMessage(messages.leaveChatConfirm),
|
||||
confirmationTheme: 'primary',
|
||||
onConfirm: () => {
|
||||
deleteChat.mutate();
|
||||
},
|
||||
onConfirm: () => deleteChat.mutate(),
|
||||
}));
|
||||
};
|
||||
|
||||
|
@ -55,7 +66,7 @@ const ChatMessageListIntro = () => {
|
|||
<>
|
||||
<Text tag='span' weight='semibold'>@{chat.account.acct}</Text>
|
||||
{' '}
|
||||
<Text tag='span'>wants to start a chat with you</Text>
|
||||
<Text tag='span'>{intl.formatMessage(messages.intro)}</Text>
|
||||
</>
|
||||
) : (
|
||||
<Text tag='span' weight='semibold'>@{chat.account.acct}</Text>
|
||||
|
@ -68,13 +79,10 @@ const ChatMessageListIntro = () => {
|
|||
<Button
|
||||
theme='primary'
|
||||
block
|
||||
onClick={() => {
|
||||
acceptChat.mutate();
|
||||
// inputRef?.current?.focus();
|
||||
}}
|
||||
onClick={() => acceptChat.mutate()}
|
||||
disabled={acceptChat.isLoading}
|
||||
>
|
||||
Accept
|
||||
{intl.formatMessage(messages.accept)}
|
||||
</Button>
|
||||
|
||||
<HStack alignItems='center' space={2} className='w-full'>
|
||||
|
@ -83,7 +91,7 @@ const ChatMessageListIntro = () => {
|
|||
block
|
||||
onClick={handleLeaveChat}
|
||||
>
|
||||
Leave chat
|
||||
{intl.formatMessage(messages.leaveChat)}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
|
@ -91,7 +99,7 @@ const ChatMessageListIntro = () => {
|
|||
block
|
||||
onClick={handleReportChat}
|
||||
>
|
||||
Report
|
||||
{intl.formatMessage(messages.report)}
|
||||
</Button>
|
||||
</HStack>
|
||||
</Stack>
|
||||
|
@ -99,7 +107,7 @@ const ChatMessageListIntro = () => {
|
|||
<HStack justifyContent='center' alignItems='center' space={1} className='flex-shrink-0'>
|
||||
<Icon src={require('@tabler/icons/clock.svg')} className='text-gray-600 w-4 h-4' />
|
||||
<Text size='sm' theme='muted'>
|
||||
Messages older than 15 days are deleted.
|
||||
{intl.formatMessage(messages.messageLifespan)}
|
||||
</Text>
|
||||
</HStack>
|
||||
)}
|
||||
|
|
|
@ -30,6 +30,10 @@ const messages = defineMessages({
|
|||
more: { id: 'chats.actions.more', defaultMessage: 'More' },
|
||||
delete: { id: 'chats.actions.delete', defaultMessage: 'Delete' },
|
||||
copy: { id: 'chats.actions.copy', defaultMessage: 'Copy' },
|
||||
blockedBy: { id: 'chat_message_list.blockedBy', defaultMessage: 'You are blocked by' },
|
||||
networkFailureTitle: { id: 'chat_message_list.network_failure.title', defaultMessage: 'Whoops!' },
|
||||
networkFailureSubtitle: { id: 'chat_message_list.network_failure.subtitle', defaultMessage: 'We encountered a network failure.' },
|
||||
networkFailureAction: { id: 'chat_message_list.network_failure.action', defaultMessage: 'Try again' },
|
||||
});
|
||||
|
||||
type TimeFormat = 'today' | 'date';
|
||||
|
@ -398,7 +402,7 @@ const ChatMessageList: React.FC<IChatMessageList> = ({ chat, autosize }) => {
|
|||
<Avatar src={chat.account.avatar} size={75} />
|
||||
<Text align='center'>
|
||||
<>
|
||||
<Text tag='span'>You are blocked by</Text>
|
||||
<Text tag='span'>{intl.formatMessage(messages.blockedBy)}</Text>
|
||||
{' '}
|
||||
<Text tag='span' theme='primary'>@{chat.account.acct}</Text>
|
||||
</>
|
||||
|
@ -413,15 +417,17 @@ const ChatMessageList: React.FC<IChatMessageList> = ({ chat, autosize }) => {
|
|||
<Stack alignItems='center' justifyContent='center' className='h-full flex-grow'>
|
||||
<Stack space={4}>
|
||||
<Stack space={1}>
|
||||
<Text size='lg' weight='bold' align='center'>Whoops!</Text>
|
||||
<Text size='lg' weight='bold' align='center'>
|
||||
{intl.formatMessage(messages.networkFailureTitle)}
|
||||
</Text>
|
||||
<Text theme='muted' align='center'>
|
||||
We encountered a network failure.
|
||||
{intl.formatMessage(messages.networkFailureSubtitle)}
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
<div className='mx-auto'>
|
||||
<Button theme='primary' onClick={() => refetch()}>
|
||||
Try again
|
||||
{intl.formatMessage(messages.networkFailureAction)}
|
||||
</Button>
|
||||
</div>
|
||||
</Stack>
|
||||
|
|
|
@ -1,16 +1,42 @@
|
|||
import React from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import { Button, Stack, Text } from 'soapbox/components/ui';
|
||||
|
||||
const Blankslate = () => (
|
||||
<Stack justifyContent='center' alignItems='center' space={4} className='px-4 h-full'>
|
||||
<Stack space={2}>
|
||||
<Text weight='semibold' size='xl' align='center'>No messages yet</Text>
|
||||
<Text theme='muted' align='center'>You can start a conversation with anyone that follows you.</Text>
|
||||
const messages = defineMessages({
|
||||
title: { id: 'chat_search.empty_results_blankslate.title', defaultMessage: 'No messages yet' },
|
||||
body: { id: 'chat_search.empty_results_blankslate.body', defaultMessage: 'You can start a conversation with anyone that follows you.' },
|
||||
action: { id: 'chat_search.empty_results_blankslate.action', defaultMessage: 'Message someone' },
|
||||
});
|
||||
|
||||
interface IBlankslate {
|
||||
onSearch(): void
|
||||
}
|
||||
|
||||
const Blankslate = ({ onSearch }: IBlankslate) => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<Stack alignItems='center' justifyContent='center' className='h-full flex-grow'>
|
||||
<Stack space={4}>
|
||||
<Stack space={1} className='max-w-[85%] mx-auto'>
|
||||
<Text size='lg' weight='bold' align='center'>
|
||||
{intl.formatMessage(messages.title)}
|
||||
</Text>
|
||||
|
||||
<Text theme='muted' align='center'>
|
||||
{intl.formatMessage(messages.body)}
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
{/* <Button theme='primary'>Message someone</Button> */}
|
||||
<div className='mx-auto'>
|
||||
<Button theme='primary' onClick={onSearch}>
|
||||
{intl.formatMessage(messages.action)}
|
||||
</Button>
|
||||
</div>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default Blankslate;
|
||||
|
|
|
@ -1,31 +1,27 @@
|
|||
import { useMutation } from '@tanstack/react-query';
|
||||
import { AxiosError } from 'axios';
|
||||
import sumBy from 'lodash/sumBy';
|
||||
import React, { useState } from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import snackbar from 'soapbox/actions/snackbar';
|
||||
import { Avatar, Button, HStack, Icon, Input, Stack, Text } from 'soapbox/components/ui';
|
||||
import VerificationBadge from 'soapbox/components/verification_badge';
|
||||
import { Icon, Input, Stack } from 'soapbox/components/ui';
|
||||
import { useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { useAppDispatch, useDebounce } from 'soapbox/hooks';
|
||||
import { useDebounce } from 'soapbox/hooks';
|
||||
import { IChat, useChats } from 'soapbox/queries/chats';
|
||||
import { queryClient } from 'soapbox/queries/client';
|
||||
import useAccountSearch from 'soapbox/queries/search';
|
||||
|
||||
import ChatList from '../chat-list';
|
||||
import ChatPaneHeader from '../chat-pane-header';
|
||||
import ChatSearch from '../chat-search/chat-search';
|
||||
import EmptyResultsBlankslate from '../chat-search/empty-results-blankslate';
|
||||
import ChatWindow from '../chat-window';
|
||||
import { Pane } from '../ui';
|
||||
|
||||
import Blankslate from './blankslate';
|
||||
|
||||
const messages = defineMessages({
|
||||
searchPlaceholder: { id: 'chats.search_placeholder', defaultMessage: 'Search inbox' },
|
||||
});
|
||||
|
||||
const ChatPane = () => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
const debounce = useDebounce;
|
||||
|
||||
const [value, setValue] = useState<string>();
|
||||
|
@ -33,17 +29,10 @@ const ChatPane = () => {
|
|||
|
||||
const { chat, setChat, isOpen, isSearching, setSearching, toggleChatPane } = useChatContext();
|
||||
const { chatsQuery: { data: chats } } = useChats(debouncedValue);
|
||||
// const chats: IChat[] = [];
|
||||
|
||||
// Screens
|
||||
// 1. Search + Chats
|
||||
// 2. Search + empty
|
||||
// 3. User search
|
||||
|
||||
|
||||
const unreadCount = sumBy(chats, (chat) => chat.unread);
|
||||
|
||||
const hasSearchValue = Number(value?.length) > 0;
|
||||
const hasSearchValue = Number(debouncedValue?.length) > 0;
|
||||
|
||||
const handleClickChat = (chat: IChat) => {
|
||||
setChat(chat);
|
||||
|
@ -88,28 +77,13 @@ const ChatPane = () => {
|
|||
fade
|
||||
/>
|
||||
) : (
|
||||
<Text>no results</Text>
|
||||
<EmptyResultsBlankslate />
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
} else if (chats?.length === 0) {
|
||||
return (
|
||||
<Stack alignItems='center' justifyContent='center' className='h-full flex-grow'>
|
||||
<Stack space={4}>
|
||||
<Stack space={1} className='max-w-[85%] mx-auto'>
|
||||
<Text size='lg' weight='bold' align='center'>No messages yet</Text>
|
||||
<Text theme='muted' align='center'>
|
||||
You can start a conversation with anyone that follows you.
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
<div className='mx-auto'>
|
||||
<Button theme='primary' onClick={() => setSearching(true)}>
|
||||
Message someone
|
||||
</Button>
|
||||
</div>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Blankslate onSearch={() => setSearching(true)} />
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,14 +1,26 @@
|
|||
import React from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import { Stack, Text } from 'soapbox/components/ui';
|
||||
|
||||
const Blankslate = () => (
|
||||
const messages = defineMessages({
|
||||
title: { id: 'chat_search.blankslate.title', defaultMessage: 'Search followers' },
|
||||
body: { id: 'chat_search.blankslate.body', defaultMessage: 'You can start a conversation with anyone that follows you.' },
|
||||
});
|
||||
|
||||
const Blankslate = () => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<Stack justifyContent='center' alignItems='center' space={2} className='h-full w-2/3 mx-auto'>
|
||||
<Text weight='bold' size='lg' align='center'>Search followers</Text>
|
||||
<Text weight='bold' size='lg' align='center'>
|
||||
{intl.formatMessage(messages.title)}
|
||||
</Text>
|
||||
<Text theme='muted' align='center'>
|
||||
You can start a conversation with anyone that follows you.
|
||||
{intl.formatMessage(messages.body)}
|
||||
</Text>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default Blankslate;
|
|
@ -1,6 +1,7 @@
|
|||
import { useMutation } from '@tanstack/react-query';
|
||||
import { AxiosError } from 'axios';
|
||||
import React, { useState } from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import snackbar from 'soapbox/actions/snackbar';
|
||||
import { HStack, Icon, Input, Stack, Text } from 'soapbox/components/ui';
|
||||
|
@ -17,9 +18,14 @@ import Blankslate from './blankslate';
|
|||
import EmptyResultsBlankslate from './empty-results-blankslate';
|
||||
import Results from './results';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'chat_search.title', defaultMessage: 'Messages' },
|
||||
});
|
||||
|
||||
const ChatSearch = () => {
|
||||
const debounce = useDebounce;
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
|
||||
const { isOpen, setChat, setSearching, toggleChatPane } = useChatContext();
|
||||
const { getOrCreateChatByAccountId } = useChats();
|
||||
|
@ -82,7 +88,9 @@ const ChatSearch = () => {
|
|||
/>
|
||||
</button>
|
||||
|
||||
<Text size='sm' weight='bold' truncate>Messages</Text>
|
||||
<Text size='sm' weight='bold' truncate>
|
||||
{intl.formatMessage(messages.title)}
|
||||
</Text>
|
||||
</HStack>
|
||||
}
|
||||
isOpen={isOpen}
|
||||
|
|
|
@ -1,14 +1,27 @@
|
|||
import React from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import { Stack, Text } from 'soapbox/components/ui';
|
||||
|
||||
const EmptyResultsBlankslate = () => (
|
||||
const messages = defineMessages({
|
||||
title: { id: 'chat_search.empty_results_blankslate.title', defaultMessage: 'No matches found' },
|
||||
body: { id: 'chat_search.empty_results_blankslate.body', defaultMessage: 'Try searching for another name.' },
|
||||
});
|
||||
|
||||
const EmptyResultsBlankslate = () => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<Stack justifyContent='center' alignItems='center' space={2} className='h-full w-2/3 mx-auto'>
|
||||
<Text weight='bold' size='lg' align='center'>No matches found</Text>
|
||||
<Text weight='bold' size='lg' align='center'>
|
||||
{intl.formatMessage(messages.title)}
|
||||
</Text>
|
||||
|
||||
<Text theme='muted' align='center'>
|
||||
Try searching for another name.
|
||||
{intl.formatMessage(messages.body)}
|
||||
</Text>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmptyResultsBlankslate;
|
|
@ -11,9 +11,10 @@ module.exports = {
|
|||
xl: '1280px',
|
||||
},
|
||||
extend: {
|
||||
boxShadow: {
|
||||
boxShadow: ({ theme }) => ({
|
||||
'3xl': '0 25px 75px -15px rgba(0, 0, 0, 0.25)',
|
||||
},
|
||||
'inset-ring': `inset 0 0 0 2px ${theme('colors.accent-blue')}`,
|
||||
}),
|
||||
fontSize: {
|
||||
base: '0.9375rem',
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue