Skip to content

Commit

Permalink
Merge pull request #43 from anuraghazra/develop
Browse files Browse the repository at this point in the history
refactor: refactored Room, MessageInput Components
  • Loading branch information
anuraghazra authored Jul 3, 2020
2 parents 631edc9 + 5588a6e commit 25d76e5
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 117 deletions.
2 changes: 1 addition & 1 deletion client/src/components/Message/MessageList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import MessageContainer from "components/Message/MessageContainer";
import { useAuthContext } from "contexts/AuthContext";

interface IMessageList {
messages?: MessageEdge[];
messages?: Partial<MessageEdge>[];
}

const MessageList: React.FC<IMessageList> = ({ messages }) => {
Expand Down
72 changes: 21 additions & 51 deletions client/src/components/MessageInput/MessageInput.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import React, { useEffect, useRef, useCallback } from "react";
import React, { useEffect, useRef } from "react";
import { FaSmile, FaPaperPlane, FaImage } from "react-icons/fa";
import { Picker } from "emoji-mart";
import "emoji-mart/css/emoji-mart.css";
import { useDropzone } from "react-dropzone";

import {
SendButton,
MessageInputWrapper,
defaultMentionStyles,
} from "./MessageInput.style";

import {
RoomMemberFragment,
useUploadImageMutation,
} from "graphql/generated/graphql";
import { Member as IMember } from "graphql/generated/graphql";

import useImageUpload from "./useImageUpload";
import { textareaAutoResize } from "utils";
import { Flex, Dropdown, IconButton, toast } from "@convoy-ui";
import { Flex, Dropdown, IconButton } from "@convoy-ui";
import { MentionsInput, Mention, OnChangeHandlerFunc } from "react-mentions";

const mql = window.matchMedia(`(min-width: 800px)`);
Expand All @@ -26,15 +23,16 @@ interface IMessageInput {
onCancel?: () => void;
handleChange: OnChangeHandlerFunc;
onEmojiClick?: (emoji: any) => void;
mentionSuggestions: RoomMemberFragment[];
mentionSuggestions: Partial<IMember>[];
handleSubmit: (event: React.FormEvent<HTMLFormElement>) => void;
innerRef?: React.MutableRefObject<HTMLTextAreaElement | undefined>;
setValue?: (value: React.SetStateAction<string>) => void;
[x: string]: any;
}
type ISuggestionsData = { display: any; id: string }[] | undefined;
// prettier-ignore
type MessageInputType = React.FC<IMessageInput> & React.HTMLAttributes<HTMLTextAreaElement>;

const MessageInput: React.FC<IMessageInput> = ({
const MessageInput: MessageInputType = ({
value,
innerRef,
onCancel,
Expand All @@ -50,6 +48,17 @@ const MessageInput: React.FC<IMessageInput> = ({
const textareaRef = useRef<HTMLTextAreaElement>();
const suggestionsData = useRef<ISuggestionsData>();

const {
open,
getRootProps,
isDragActive,
getInputProps,
uploadImageInProgress,
} = useImageUpload({
value,
setValue,
});

const imparativeSubmit = (event: any) => {
event.preventDefault();
formRef?.current.dispatchEvent(new Event("submit", { cancelable: true }));
Expand Down Expand Up @@ -85,53 +94,14 @@ const MessageInput: React.FC<IMessageInput> = ({
});
}, [mentionSuggestions]);

// Image uploading
const [
uploadImage,
{ loading: uploadImageInProgress },
] = useUploadImageMutation({
onCompleted(data) {
const replacedPlaceholder = value.replace(
"![Uplading image...](...please wait)",
`![Alt Text](${data.uploadImage.url})`
);
setValue && setValue(replacedPlaceholder);
},
onError(err) {
toast.error("Something went wrong uploading image.");
},
});

const handleOnDrop = useCallback(
acceptedFiles => {
uploadImage({
variables: {
file: acceptedFiles[0],
},
});
},
[uploadImage]
);

const { getRootProps, getInputProps, open, isDragActive } = useDropzone({
onDrop: handleOnDrop,
onDropAccepted: () => {
setValue && setValue(value + `\n\n![Uplading image...](...please wait)`);
},
accept: "image/jpeg, image/png",
multiple: false,
noClick: true,
noKeyboard: true,
});

return (
<MessageInputWrapper className="message__input">
<Flex gap="large" align="center" justify="space-between" nowrap>
<IconButton
onClick={open}
icon={<FaImage />}
data-testid="upload-button"
isLoading={uploadImageInProgress}
icon={<FaImage />}
onClick={open}
/>

<form
Expand Down
60 changes: 60 additions & 0 deletions client/src/components/MessageInput/useImageUpload.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { useCallback } from "react";
import { useDropzone } from "react-dropzone";

import { toast } from "@convoy-ui";
import { useUploadImageMutation } from "graphql/generated/graphql";

interface IUseImageUpload {
value: string;
setValue: (value: React.SetStateAction<string>) => void;
}
const useImageUpload = ({ value, setValue }: IUseImageUpload) => {
// Image uploading
const [
uploadImage,
{ loading: uploadImageInProgress },
] = useUploadImageMutation({
onCompleted(data) {
const replacedPlaceholder = value.replace(
"![Uplading image...](...please wait)",
`![Alt Text](${data.uploadImage.url})`
);
setValue && setValue(replacedPlaceholder);
},
onError(err) {
toast.error("Something went wrong uploading image.");
},
});

const handleOnDrop = useCallback(
acceptedFiles => {
uploadImage({
variables: {
file: acceptedFiles[0],
},
});
},
[uploadImage]
);

const { getRootProps, getInputProps, open, isDragActive } = useDropzone({
onDrop: handleOnDrop,
onDropAccepted: () => {
setValue && setValue(value + `\n\n![Uplading image...](...please wait)`);
},
accept: "image/jpeg, image/png",
multiple: false,
noClick: true,
noKeyboard: true,
});

return {
open,
isDragActive,
getRootProps,
getInputProps,
uploadImageInProgress,
};
};

export default useImageUpload;
81 changes: 16 additions & 65 deletions client/src/pages/Room/Room.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,21 @@
import React, { useCallback, useEffect, useRef, useState } from "react";
import React, { useEffect, useRef, useState } from "react";
import { useParams } from "react-router-dom";
import update from "immutability-helper";
import styled from "styled-components";
import Sidebar from "react-sidebar";

import useMessageInput from "components/MessageInput/useMessageInput";
import useResponsiveSidebar from "hooks/useResponsiveSidebar";

import {
updateCacheAfterSendMessage,
sendMessageOptimisticResponse,
} from "./Room.helpers";
import {
MessageEdge,
useGetRoomQuery,
useSendMessageMutation,
} from "graphql/generated/graphql";
import { useGetRoomQuery } from "graphql/generated/graphql";
import { Flex } from "@convoy-ui";
import { scrollToBottom } from "utils";
import { MAX_MESSAGES } from "../../constants";
import { useAuthContext } from "contexts/AuthContext";
import useResponsiveSidebar from "hooks/useResponsiveSidebar";

import RoomHeader from "./RoomHeader";
import SendMessage from "./SendMessage";
import RightSidebar from "./RightSidebar";
import subscribeToMessages from "./subscribeToMessages";
import MessageList from "components/Message/MessageList";
import MessageInput from "components/MessageInput/MessageInput";
import BidirectionalScroller from "components/BidirectionalScroller";
import { DashboardBody } from "pages/Dashboard/Dashboard.style";

Expand All @@ -51,13 +41,6 @@ const Room: React.FC = () => {
const bodyRef = useRef<HTMLElement>();

const { isDocked, isOpen, setIsOpen } = useResponsiveSidebar();
const {
value,
setValue,
textareaRef,
handleChange,
handleEmojiClick,
} = useMessageInput();
const [isFetchingMore, setIsFetchingMore] = useState<boolean>(false);

// fetch room query
Expand All @@ -80,33 +63,6 @@ const Room: React.FC = () => {
},
});

// send message mutation
const [sendMessage, { error: sendError }] = useSendMessageMutation({
optimisticResponse: sendMessageOptimisticResponse(roomId, value, user),
onError(err) {
console.log(err);
},
update: updateCacheAfterSendMessage,
});

// submit message
const onMessageSubmit = useCallback(
(event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
sendMessage({
variables: {
content: (event.target as any).message.value,
roomId: roomId,
},
});
setValue("");
window.setTimeout(() => {
scrollToBottom(bodyRef?.current);
}, 50);
},
[]
);

useEffect(() => {
subscribeToMessages(
subscribeToMore,
Expand Down Expand Up @@ -140,6 +96,12 @@ const Room: React.FC = () => {
});
};

const handleOnReachTop = (restoreScroll: () => void) => {
if (roomData?.messages?.pageInfo?.hasNext) {
fetchPreviousMessages().then(restoreScroll);
}
};

return (
<>
<Sidebar
Expand All @@ -154,7 +116,6 @@ const Room: React.FC = () => {
}
>
<RoomBody>
{sendError && <span>{sendError?.message}</span>}
{fetchRoomError && <span>{fetchRoomError?.message}</span>}

<Flex
Expand All @@ -169,25 +130,15 @@ const Room: React.FC = () => {
<BidirectionalScroller
innerRef={bodyRef}
topLoading={isFetchingMore}
onReachTop={restoreScroll => {
if (roomData?.messages?.pageInfo?.hasNext) {
fetchPreviousMessages().then(restoreScroll);
}
}}
onReachTop={handleOnReachTop}
>
<MessageList
messages={roomData?.messages?.edges as MessageEdge[]}
/>
<MessageList messages={roomData?.messages?.edges} />
</BidirectionalScroller>

<MessageInput
value={value}
setValue={setValue}
innerRef={textareaRef}
handleSubmit={onMessageSubmit}
handleChange={handleChange}
onEmojiClick={handleEmojiClick}
mentionSuggestions={roomData?.room?.members}
<SendMessage
roomId={roomId}
bodyRef={bodyRef}
members={roomData?.room?.members}
/>
</MessagesWrapper>
</Flex>
Expand Down
Loading

0 comments on commit 25d76e5

Please sign in to comment.