Add ability to accept chat
This commit is contained in:
parent
1ed1f3fd2e
commit
8492cc59e2
|
@ -0,0 +1,24 @@
|
|||
import React, { createContext, useContext, useState } from 'react';
|
||||
|
||||
import type { IChat } from 'soapbox/queries/chats';
|
||||
|
||||
const ChatContext = createContext<any>({
|
||||
chat: null,
|
||||
});
|
||||
|
||||
const ChatProvider: React.FC = ({ children }) => {
|
||||
const [chat, setChat] = useState<IChat>();
|
||||
|
||||
return (
|
||||
<ChatContext.Provider value={{ chat, setChat }}>{children}</ChatContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
interface IChatContext {
|
||||
chat: IChat | null
|
||||
setChat: React.Dispatch<React.SetStateAction<IChat | null>>
|
||||
}
|
||||
|
||||
const useChatContext = (): IChatContext => useContext(ChatContext);
|
||||
|
||||
export { ChatContext, ChatProvider, useChatContext };
|
|
@ -8,7 +8,7 @@ import {
|
|||
markChatRead,
|
||||
} from 'soapbox/actions/chats';
|
||||
import { uploadMedia } from 'soapbox/actions/media';
|
||||
import { HStack, Icon, IconButton, Input, Stack, Textarea } from 'soapbox/components/ui';
|
||||
import { Avatar, Button, HStack, Icon, IconButton, Input, Stack, Text, Textarea } from 'soapbox/components/ui';
|
||||
import UploadProgress from 'soapbox/components/upload-progress';
|
||||
import UploadButton from 'soapbox/features/compose/components/upload_button';
|
||||
import { useAppSelector, useAppDispatch, useOwnAccount } from 'soapbox/hooks';
|
||||
|
@ -41,7 +41,7 @@ const ChatBox: React.FC<IChatBox> = ({ chat, onSetInputRef, autosize }) => {
|
|||
const chatMessageIds = useAppSelector(state => state.chat_message_lists.get(chat.id, ImmutableOrderedSet<string>()));
|
||||
const account = useOwnAccount();
|
||||
|
||||
const { createChatMessage, markChatAsRead } = useChat(chat.id);
|
||||
const { createChatMessage, markChatAsRead, acceptChat } = useChat(chat.id);
|
||||
|
||||
const [content, setContent] = useState<string>('');
|
||||
const [attachment, setAttachment] = useState<any>(undefined);
|
||||
|
@ -51,6 +51,8 @@ const ChatBox: React.FC<IChatBox> = ({ chat, onSetInputRef, autosize }) => {
|
|||
|
||||
const inputElem = useRef<HTMLTextAreaElement | null>(null);
|
||||
|
||||
const needsAcceptance = !chat.accepted && chat.created_by_account !== account?.id;
|
||||
|
||||
const isSubmitDisabled = content.length === 0 && !attachment;
|
||||
|
||||
// TODO: needs last_read_id param
|
||||
|
@ -216,8 +218,37 @@ const ChatBox: React.FC<IChatBox> = ({ chat, onSetInputRef, autosize }) => {
|
|||
|
||||
return (
|
||||
<Stack className='overflow-hidden flex flex-grow' onMouseOver={handleMouseOver}>
|
||||
<div className='flex-grow h-full overflow-hidden'>
|
||||
<ChatMessageList chatMessageIds={chatMessageIds} chat={chat} autosize />
|
||||
<div className='flex-grow h-full overflow-hidden flex justify-center'>
|
||||
{needsAcceptance ? (
|
||||
<Stack justifyContent='center' alignItems='center' space={5} className='w-3/4 mx-auto'>
|
||||
<Stack alignItems='center' space={2}>
|
||||
<Avatar src={chat.account.avatar_static} size={75} />
|
||||
<Text size='lg' align='center'>
|
||||
<Text tag='span' weight='semibold'>@{chat.account.acct}</Text>
|
||||
{' '}
|
||||
<Text tag='span'>wants to start a chat with you</Text>
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
<Stack space={2} className='w-full'>
|
||||
<Button
|
||||
theme='primary'
|
||||
block
|
||||
onClick={() => acceptChat.mutate()}
|
||||
disabled={acceptChat.isLoading}
|
||||
>
|
||||
Accept
|
||||
</Button>
|
||||
|
||||
<HStack alignItems='center' space={2} className='w-full'>
|
||||
<Button theme='accent' block>Leave chat</Button>
|
||||
<Button theme='secondary' block>Report</Button>
|
||||
</HStack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
) : (
|
||||
<ChatMessageList chatMessageIds={chatMessageIds} chat={chat} autosize />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className='mt-auto p-4 shadow-3xl'>
|
||||
|
|
|
@ -275,7 +275,7 @@ const ChatMessageList: React.FC<IChatMessageList> = ({ chat, chatMessageIds, aut
|
|||
})}
|
||||
>
|
||||
{isMyMessage ? (
|
||||
<div className='hidden group-hover:block mr-2 text-gray-500'>
|
||||
<div className='hidden focus:block group-hover:block mr-2 text-gray-500'>
|
||||
<DropdownMenuContainer
|
||||
items={menu}
|
||||
src={require('@tabler/icons/dots.svg')}
|
||||
|
|
|
@ -13,6 +13,7 @@ import snackbar from 'soapbox/actions/snackbar';
|
|||
import AccountSearch from 'soapbox/components/account_search';
|
||||
import { Avatar, Button, Counter, HStack, Icon, IconButton, Input, Spinner, Stack, Text } from 'soapbox/components/ui';
|
||||
import VerificationBadge from 'soapbox/components/verification_badge';
|
||||
import { ChatProvider, useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import AudioToggle from 'soapbox/features/chats/components/audio-toggle';
|
||||
import PlaceholderAccount from 'soapbox/features/placeholder/components/placeholder_account';
|
||||
import { useAppDispatch, useAppSelector, useDebounce, useSettings } from 'soapbox/hooks';
|
||||
|
@ -47,12 +48,13 @@ const makeNormalizeChatPanes = () => createSelector([
|
|||
|
||||
const normalizeChatPanes = makeNormalizeChatPanes();
|
||||
|
||||
const ChatPanes = () => {
|
||||
const ChatPane = () => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
const debounce = useDebounce;
|
||||
|
||||
const [chat, setChat] = useState<IChat | null>();
|
||||
const { chat, setChat } = useChatContext();
|
||||
|
||||
const [value, setValue] = useState<string>();
|
||||
const debouncedValue = debounce(value as string, 300);
|
||||
|
||||
|
@ -210,4 +212,4 @@ const ChatPanes = () => {
|
|||
);
|
||||
};
|
||||
|
||||
export default ChatPanes;
|
||||
export default ChatPane;
|
|
@ -0,0 +1,15 @@
|
|||
import React from 'react';
|
||||
|
||||
import { ChatProvider } from 'soapbox/contexts/chat-context';
|
||||
|
||||
import ChatPane from './chat-pane';
|
||||
|
||||
const ChatWidget = () => {
|
||||
return (
|
||||
<ChatProvider>
|
||||
<ChatPane />
|
||||
</ChatProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChatWidget;
|
|
@ -89,7 +89,7 @@ import {
|
|||
MfaForm,
|
||||
ChatIndex,
|
||||
ChatRoom,
|
||||
ChatPanes,
|
||||
ChatWidget,
|
||||
ServerInfo,
|
||||
Dashboard,
|
||||
ModerationLog,
|
||||
|
@ -680,7 +680,7 @@ const UI: React.FC = ({ children }) => {
|
|||
</BundleContainer>
|
||||
)}
|
||||
{me && features.chats && !mobile && (
|
||||
<BundleContainer fetchComponent={ChatPanes}>
|
||||
<BundleContainer fetchComponent={ChatWidget}>
|
||||
{Component => <Component />}
|
||||
</BundleContainer>
|
||||
)}
|
||||
|
|
|
@ -318,8 +318,8 @@ export function ChatRoom() {
|
|||
return import(/* webpackChunkName: "features/chats/chat_room" */'../../chats/chat-room');
|
||||
}
|
||||
|
||||
export function ChatPanes() {
|
||||
return import(/* webpackChunkName: "features/chats/components/chat_panes" */'../../chats/components/chat-panes');
|
||||
export function ChatWidget() {
|
||||
return import(/* webpackChunkName: "features/chats/components/chat-widget" */'../../chats/components/chat-widget');
|
||||
}
|
||||
|
||||
export function ServerInfo() {
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import { useInfiniteQuery, useQuery } from '@tanstack/react-query';
|
||||
import { useInfiniteQuery, useMutation, useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { useApi } from 'soapbox/hooks';
|
||||
|
||||
import { queryClient } from './client';
|
||||
|
||||
export interface IChat {
|
||||
id: string
|
||||
unread: number
|
||||
created_by_account: number
|
||||
created_by_account: string
|
||||
last_message: null | string
|
||||
created_at: Date
|
||||
updated_at: Date
|
||||
|
@ -90,6 +93,7 @@ const useChats = () => {
|
|||
|
||||
const useChat = (chatId: string) => {
|
||||
const api = useApi();
|
||||
const { setChat } = useChatContext();
|
||||
|
||||
const markChatAsRead = () => api.post<IChat>(`/api/v1/pleroma/chats/${chatId}/read`);
|
||||
|
||||
|
@ -99,7 +103,15 @@ const useChat = (chatId: string) => {
|
|||
|
||||
const deleteChatMessage = (chatMessageId: string) => api.delete<IChat>(`/api/v1/pleroma/chats/${chatId}/messages/${chatMessageId}`);
|
||||
|
||||
return { createChatMessage, markChatAsRead, deleteChatMessage };
|
||||
const acceptChat = useMutation(() => api.post<IChat>(`/api/v1/pleroma/chats/${chatId}/accept`), {
|
||||
onSuccess(response) {
|
||||
setChat(response.data);
|
||||
queryClient.invalidateQueries(['chats', 'messages', chatId]);
|
||||
queryClient.invalidateQueries(['chats']);
|
||||
},
|
||||
});
|
||||
|
||||
return { createChatMessage, markChatAsRead, deleteChatMessage, acceptChat };
|
||||
};
|
||||
|
||||
export { useChat, useChats, useChatMessages };
|
||||
|
|
Loading…
Reference in New Issue