Skip to content

Commit

Permalink
message sending working
Browse files Browse the repository at this point in the history
  • Loading branch information
YubaNeupane committed Sep 21, 2023
1 parent e42ceff commit 0e36175
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 14 deletions.
61 changes: 48 additions & 13 deletions components/chat/chat-messages.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
"use client";

import { Fragment, useRef, ElementRef } from "react";
import { format } from "date-fns";
import { Member, Message, Profile } from "@prisma/client";
import { ChatWelcome } from "./chat-welcome";
import { useChatQuery } from "@/hooks/use-chat-query";
import { Loader2, ServerCrash } from "lucide-react";
import { Fragment } from "react";
import { ChatItem } from "./chat-item";
import { format } from "date-fns";

import { useChatQuery } from "@/hooks/use-chat-query";
import { useChatSocket } from "@/hooks/use-chat-socket";
import { useChatScroll } from "@/hooks/use-chat-scroll";

import { ChatWelcome } from "./chat-welcome";
import { ChatItem } from "./chat-item";

const DATE_FORMAT = "d MMM yyyy, HH:mm";

type MessageWithMemberWithProfile = Message & {
member: Member & { profile: Profile };
member: Member & {
profile: Profile;
};
};

interface ChatMessagesProps {
Expand Down Expand Up @@ -42,10 +47,24 @@ export const ChatMessages = ({
const addKey = `chat:${chatId}:messages`;
const updateKey = `chat:${chatId}:messages:update`;

const { data, fetchMessages, hasNextPage, isFetchingNextPage, status } =
useChatQuery({ queryKey, apiUrl, paramKey, paramValue });
const chatRef = useRef<ElementRef<"div">>(null);
const bottomRef = useRef<ElementRef<"div">>(null);

const { data, fetchNextPage, hasNextPage, isFetchingNextPage, status } =
useChatQuery({
queryKey,
apiUrl,
paramKey,
paramValue,
});
useChatSocket({ queryKey, addKey, updateKey });
useChatScroll({
chatRef,
bottomRef,
loadMore: fetchNextPage,
shouldLoadMore: !isFetchingNextPage && !!hasNextPage,
count: data?.pages?.[0]?.items?.length ?? 0,
});

if (status === "loading") {
return (
Expand All @@ -68,19 +87,34 @@ export const ChatMessages = ({
</div>
);
}

return (
<div className="flex flex-col flex-1 py-4 overflow-y-auto">
<div className="flex-1" />
<ChatWelcome type={type} name={name} />
<div ref={chatRef} className="flex flex-col flex-1 py-4 overflow-y-auto">
{!hasNextPage && <div className="flex-1" />}
{!hasNextPage && <ChatWelcome type={type} name={name} />}
{hasNextPage && (
<div className="flex justify-center">
{isFetchingNextPage ? (
<Loader2 className="w-6 h-6 my-4 text-zinc-500 animate-spin" />
) : (
<button
onClick={() => fetchNextPage()}
className="my-4 text-xs transition text-zinc-500 hover:text-zinc-600 dark:text-zinc-400 dark:hover:text-zinc-300"
>
Load previous messages
</button>
)}
</div>
)}
<div className="flex flex-col-reverse mt-auto">
{data?.pages.map((group, i) => (
{data?.pages?.map((group, i) => (
<Fragment key={i}>
{group.items.map((message: MessageWithMemberWithProfile) => (
<ChatItem
key={message.id}
id={message.id}
currentMember={member}
member={message.member}
id={message.id}
content={message.content}
fileUrl={message.fileUrl}
deleted={message.deleted}
Expand All @@ -93,6 +127,7 @@ export const ChatMessages = ({
</Fragment>
))}
</div>
<div ref={bottomRef} />
</div>
);
};
2 changes: 1 addition & 1 deletion hooks/use-chat-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const useChatQuery = ({

return {
data,
fetchMessages,
fetchNextPage,
hasNextPage,
isFetchingNextPage,
status,
Expand Down
64 changes: 64 additions & 0 deletions hooks/use-chat-scroll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { useEffect, useState } from "react";

type ChatScrollProps = {
chatRef: React.RefObject<HTMLDivElement>;
bottomRef: React.RefObject<HTMLDivElement>;
shouldLoadMore: boolean;
loadMore: () => void;
count: number;
};

export const useChatScroll = ({
chatRef,
bottomRef,
shouldLoadMore,
loadMore,
count,
}: ChatScrollProps) => {
const [hasInitialized, setHasInitialized] = useState(false);

useEffect(() => {
const topDiv = chatRef?.current;

const handleScroll = () => {
const scrollTop = topDiv?.scrollTop;

if (scrollTop === 0 && shouldLoadMore) {
loadMore();
}
};

topDiv?.addEventListener("scroll", handleScroll);

return () => {
topDiv?.removeEventListener("scroll", handleScroll);
};
}, [shouldLoadMore, loadMore, chatRef]);

useEffect(() => {
const bottomDiv = bottomRef?.current;
const topDiv = chatRef.current;
const shouldAutoScroll = () => {
if (!hasInitialized && bottomDiv) {
setHasInitialized(true);
return true;
}

if (!topDiv) {
return false;
}

const distanceFromBottom =
topDiv.scrollHeight - topDiv.scrollTop - topDiv.clientHeight;
return distanceFromBottom <= 100;
};

if (shouldAutoScroll()) {
setTimeout(() => {
bottomRef.current?.scrollIntoView({
behavior: "smooth",
});
}, 100);
}
}, [bottomRef, chatRef, count, hasInitialized]);
};

0 comments on commit 0e36175

Please sign in to comment.