ADDED SOCKET PROVIDER fixed a typo in file names
This commit is contained in:
parent
adea34b31b
commit
c517a1f354
@ -4,8 +4,9 @@ import { Open_Sans } from 'next/font/google'
|
|||||||
import { ClerkProvider } from '@clerk/nextjs'
|
import { ClerkProvider } from '@clerk/nextjs'
|
||||||
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { ThemeProvider } from '@/components/providors/theme-providor'
|
import { ThemeProvider } from '@/components/providers/theme-provider'
|
||||||
import { ModalProvidor } from '@/components/providors/modal-providor'
|
import { ModalProvider } from '@/components/providers/modal-provider'
|
||||||
|
import { SocketProvider } from '@/components/providers/socket-provider'
|
||||||
|
|
||||||
const font = Open_Sans({ subsets: ['latin'] })
|
const font = Open_Sans({ subsets: ['latin'] })
|
||||||
|
|
||||||
@ -32,8 +33,10 @@ export default function RootLayout({
|
|||||||
enableSystem={false}
|
enableSystem={false}
|
||||||
storageKey="discord-theme"
|
storageKey="discord-theme"
|
||||||
>
|
>
|
||||||
<ModalProvidor/>
|
<SocketProvider>
|
||||||
|
<ModalProvider/>
|
||||||
{children}
|
{children}
|
||||||
|
</SocketProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Hash, Menu } from "lucide-react"
|
import { Hash, Menu } from "lucide-react"
|
||||||
import { MobileToggle } from "@/components/mobile-toggle";
|
import { MobileToggle } from "@/components/mobile-toggle";
|
||||||
import { UserAvatar } from "../user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
|
import { SocketIndicator } from "@/components/socket-indicator";
|
||||||
|
|
||||||
interface ChatHeaderProps {
|
interface ChatHeaderProps {
|
||||||
serverId: string;
|
serverId: string;
|
||||||
@ -31,6 +32,9 @@ export const ChatHeader = ({
|
|||||||
<p className="font-semibold text-md text-black dark:text-white">
|
<p className="font-semibold text-md text-black dark:text-white">
|
||||||
{name}
|
{name}
|
||||||
</p>
|
</p>
|
||||||
|
<div className="ml-auto flex items-center">
|
||||||
|
<SocketIndicator/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -12,7 +12,7 @@ import { DeleteServerModal } from "@/components/modals/delete-server-modal";
|
|||||||
import { DeleteChannelModal } from "@/components/modals/delete-channel-modal";
|
import { DeleteChannelModal } from "@/components/modals/delete-channel-modal";
|
||||||
import { EditChannelModal } from "@/components/modals/edit-channel-modal";
|
import { EditChannelModal } from "@/components/modals/edit-channel-modal";
|
||||||
|
|
||||||
export const ModalProvidor = () => {
|
export const ModalProvider = () => {
|
||||||
const [isMounted, setIsMounted] = useState(false);
|
const [isMounted, setIsMounted] = useState(false);
|
||||||
|
|
||||||
useEffect (() => {
|
useEffect (() => {
|
59
components/providers/socket-provider.tsx
Normal file
59
components/providers/socket-provider.tsx
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import {
|
||||||
|
createContext,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useState
|
||||||
|
} from "react";
|
||||||
|
import { io as ClientIO } from "socket.io-client";
|
||||||
|
|
||||||
|
type SocketContextType = {
|
||||||
|
socket: any | null;
|
||||||
|
isConnected: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const SocketContext = createContext<SocketContextType>({
|
||||||
|
socket: null,
|
||||||
|
isConnected: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const useSocket = () => {
|
||||||
|
return useContext(SocketContext);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SocketProvider = ({
|
||||||
|
children
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode
|
||||||
|
}) => {
|
||||||
|
const [socket, setSocket] = useState(null);
|
||||||
|
const [isConnected, setIsConnected] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const socketInstance = new (ClientIO as any)(process.env.NEXT_PUBLIC_SITE_URL!, {
|
||||||
|
path: "/api/socket/io",
|
||||||
|
addTrailingSlash: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
socketInstance.on("connect", () => {
|
||||||
|
setIsConnected(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
socketInstance.on("disconnect", () => {
|
||||||
|
setIsConnected(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
setSocket(socketInstance);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
socketInstance.disconnect();
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SocketContext.Provider value={{ socket, isConnected }}>
|
||||||
|
{children}
|
||||||
|
</SocketContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
28
components/socket-indicator.tsx
Normal file
28
components/socket-indicator.tsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useSocket } from "@/components/providers/socket-provider";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
|
||||||
|
export const SocketIndicator = () => {
|
||||||
|
const { isConnected } = useSocket();
|
||||||
|
|
||||||
|
if (!isConnected) {
|
||||||
|
return (
|
||||||
|
<Badge
|
||||||
|
variant="outline"
|
||||||
|
className="bg-yellow-600 text-white border-none"
|
||||||
|
>
|
||||||
|
Fallback: Polling every 1s
|
||||||
|
</Badge>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Badge
|
||||||
|
variant="outline"
|
||||||
|
className="bg-emerald-600 text-white border-none"
|
||||||
|
>
|
||||||
|
Live: Real-time Updates
|
||||||
|
</Badge>
|
||||||
|
)
|
||||||
|
}
|
26
pages/api/socket/io.ts
Normal file
26
pages/api/socket/io.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { Server as NetServer } from 'http';
|
||||||
|
import { NextApiRequest } from 'next';
|
||||||
|
import { Server as ServerIO } from 'socket.io';
|
||||||
|
|
||||||
|
import { NextApiResponseServerIo } from '@/types';
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
api: {
|
||||||
|
bodyParser: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ioHandler = (req: NextApiRequest, res: NextApiResponseServerIo) => {
|
||||||
|
if (!res.socket.server.io) {
|
||||||
|
const path = "/api/socket/io"
|
||||||
|
const httpServer: NetServer = res.socket.server as any;
|
||||||
|
const io = new ServerIO(httpServer, {
|
||||||
|
path: path,
|
||||||
|
addTrailingSlash: false,
|
||||||
|
});
|
||||||
|
res.socket.server.io = io;
|
||||||
|
}
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ioHandler;
|
11
types.ts
11
types.ts
@ -1,5 +1,16 @@
|
|||||||
|
import { Server as NetServer, Socket } from 'net';
|
||||||
|
import { NextApiResponse } from 'next';
|
||||||
|
import { Server as SocketIOServer } from 'socket.io';
|
||||||
import { Server, Member, Profile } from '@prisma/client';
|
import { Server, Member, Profile } from '@prisma/client';
|
||||||
|
|
||||||
export type ServerWithMembersWithProfiles = Server & {
|
export type ServerWithMembersWithProfiles = Server & {
|
||||||
members: (Member & { profile: Profile })[];
|
members: (Member & { profile: Profile })[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type NextApiResponseServerIo = NextApiResponse & {
|
||||||
|
socket: Socket & {
|
||||||
|
server: NetServer & {
|
||||||
|
io: SocketIOServer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user