PATCH: Username was not being accessed in chat.py:
The WebSockets used for chat do not maintain the same session context as regular HTTP routes and so, the username in Flask's session could not be accessed.
This commit is contained in:
@@ -2,7 +2,6 @@ import { useState, useEffect } from "react";
|
||||
import { AuthContext } from "./context/AuthContext";
|
||||
import { StreamsProvider } from "./context/StreamsContext";
|
||||
import { BrowserRouter, Routes, Route } from "react-router-dom";
|
||||
import { SocketProvider } from "./context/SocketContext";
|
||||
import HomePage from "./pages/HomePage";
|
||||
import StreamerRoute from "./components/Stream/StreamerRoute";
|
||||
import NotFoundPage from "./pages/NotFoundPage";
|
||||
@@ -26,7 +25,6 @@ function App() {
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ isLoggedIn, username, setIsLoggedIn, setUsername }}>
|
||||
<SocketProvider>
|
||||
<StreamsProvider>
|
||||
<BrowserRouter>
|
||||
<Routes>
|
||||
@@ -39,7 +37,6 @@ function App() {
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
</StreamsProvider>
|
||||
</SocketProvider>
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,17 +16,20 @@ interface ChatPanelProps {
|
||||
}
|
||||
|
||||
const ChatPanel: React.FC<ChatPanelProps> = ({ streamId }) => {
|
||||
const { socket, isConnected } = useSocket();
|
||||
const [messages, setMessages] = useState<ChatMessage[]>([]);
|
||||
const [inputMessage, setInputMessage] = useState("");
|
||||
const chatContainerRef = useRef<HTMLDivElement>(null);
|
||||
const { isLoggedIn, username } = useAuth();
|
||||
const { socket, isConnected } = useSocket();
|
||||
|
||||
// Join chat room when component mounts
|
||||
useEffect(() => {
|
||||
if (socket && isConnected) {
|
||||
// Join chat room
|
||||
socket.emit("join", { stream_id: streamId });
|
||||
// Add username check
|
||||
socket.emit("join", {
|
||||
username: username ? username : "Guest",
|
||||
stream_id: streamId,
|
||||
});
|
||||
|
||||
// Handle beforeunload event
|
||||
const handleBeforeUnload = () => {
|
||||
@@ -53,6 +56,7 @@ const ChatPanel: React.FC<ChatPanelProps> = ({ streamId }) => {
|
||||
|
||||
// Handle incoming messages
|
||||
socket.on("new_message", (data: ChatMessage) => {
|
||||
console.log("New message:", data);
|
||||
setMessages((prev) => [...prev, data]);
|
||||
});
|
||||
|
||||
@@ -61,10 +65,9 @@ const ChatPanel: React.FC<ChatPanelProps> = ({ streamId }) => {
|
||||
window.removeEventListener("beforeunload", handleBeforeUnload);
|
||||
socket.emit("leave", { stream_id: streamId });
|
||||
socket.disconnect();
|
||||
socket.off("new_message");
|
||||
};
|
||||
}
|
||||
}, [socket, isConnected, streamId]);
|
||||
}, [socket, isConnected, username, streamId]);
|
||||
|
||||
// Auto-scroll to bottom when new messages arrive
|
||||
useEffect(() => {
|
||||
@@ -81,6 +84,7 @@ const ChatPanel: React.FC<ChatPanelProps> = ({ streamId }) => {
|
||||
}
|
||||
|
||||
socket.emit("send_message", {
|
||||
username: username,
|
||||
stream_id: streamId,
|
||||
message: inputMessage.trim(),
|
||||
});
|
||||
@@ -111,68 +115,71 @@ const ChatPanel: React.FC<ChatPanelProps> = ({ streamId }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="chat-panel" className="h-full flex flex-col rounded-lg p-4">
|
||||
<h2 className="text-xl font-bold mb-4 text-white">Stream Chat</h2>
|
||||
<div id="chat-panel" className="h-full flex flex-col rounded-lg p-4">
|
||||
<h2 className="text-xl font-bold mb-4 text-white">Stream Chat</h2>
|
||||
|
||||
<div
|
||||
ref={chatContainerRef}
|
||||
id="chat-message-list"
|
||||
className="flex-grow w-full max-h-[50vh] overflow-y-auto mb-4 space-y-2"
|
||||
>
|
||||
{messages.map((msg, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="grid grid-cols-[8%_minmax(15%,_100px)_1fr] items-center bg-gray-700 rounded p-2 text-white"
|
||||
>
|
||||
<span className="text-gray-400 text-sm">
|
||||
{new Date(msg.time_sent).toLocaleTimeString()}
|
||||
</span>
|
||||
<span
|
||||
className={`font-bold ${
|
||||
msg.chatter_username === username ? "text-blue-400" : "text-green-400"
|
||||
}`}
|
||||
<div
|
||||
ref={chatContainerRef}
|
||||
id="chat-message-list"
|
||||
className="flex-grow w-full max-h-[50vh] overflow-y-auto mb-4 space-y-2"
|
||||
>
|
||||
{messages.map((msg, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="grid grid-cols-[8%_minmax(15%,_100px)_1fr] items-center bg-gray-700 rounded p-2 text-white"
|
||||
>
|
||||
{" "}
|
||||
{msg.chatter_username}:{" "}
|
||||
</span>
|
||||
<span>{msg.message}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<span className="text-gray-400 text-sm">
|
||||
{new Date(msg.time_sent).toLocaleTimeString()}
|
||||
</span>
|
||||
<span
|
||||
className={`font-bold ${
|
||||
msg.chatter_username === username
|
||||
? "text-blue-400"
|
||||
: "text-green-400"
|
||||
}`}
|
||||
>
|
||||
{" "}
|
||||
{msg.chatter_username}:{" "}
|
||||
</span>
|
||||
<span>{msg.message}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex justify-center gap-2">
|
||||
{isLoggedIn &&
|
||||
<>
|
||||
<Input
|
||||
type="text"
|
||||
value={inputMessage}
|
||||
onChange={(e) => setInputMessage(e.target.value)}
|
||||
onKeyDown={handleKeyPress}
|
||||
placeholder={isLoggedIn ? "Type a message..." : "Login to chat"}
|
||||
disabled={!isLoggedIn}
|
||||
extraClasses="flex-grow"
|
||||
onClick={() => (!isLoggedIn && setShowAuthModal(true))} />
|
||||
<div className="flex justify-center gap-2">
|
||||
{isLoggedIn && (
|
||||
<>
|
||||
<Input
|
||||
type="text"
|
||||
value={inputMessage}
|
||||
onChange={(e) => setInputMessage(e.target.value)}
|
||||
onKeyDown={handleKeyPress}
|
||||
placeholder={isLoggedIn ? "Type a message..." : "Login to chat"}
|
||||
disabled={!isLoggedIn}
|
||||
extraClasses="flex-grow"
|
||||
onClick={() => !isLoggedIn && setShowAuthModal(true)}
|
||||
/>
|
||||
<button
|
||||
onClick={sendChat}
|
||||
className="px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700"
|
||||
>
|
||||
Send
|
||||
</button>
|
||||
</>
|
||||
}
|
||||
|
||||
{!isLoggedIn &&
|
||||
<Button
|
||||
extraClasses="absolute top-[20px] left-[20px] text-[1rem] flex items-center flex-nowrap z-[999]"
|
||||
onClick={() => (setShowAuthModal(true))}></Button>
|
||||
}
|
||||
</>
|
||||
)}
|
||||
|
||||
</div>
|
||||
{showAuthModal && (
|
||||
<div className="fixed inset-0 z-[9999] flex items-center justify-center">
|
||||
<AuthModal onClose={() => setShowAuthModal(false)} />
|
||||
{!isLoggedIn && (
|
||||
<Button
|
||||
extraClasses="absolute top-[20px] left-[20px] text-[1rem] flex items-center flex-nowrap z-[999]"
|
||||
onClick={() => setShowAuthModal(true)}
|
||||
></Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{showAuthModal && (
|
||||
<div className="fixed inset-0 z-[9999] flex items-center justify-center">
|
||||
<AuthModal onClose={() => setShowAuthModal(false)} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -12,9 +12,9 @@ export const SocketProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
children,
|
||||
}) => {
|
||||
const [socket, setSocket] = useState<Socket | null>(null);
|
||||
const socketRef = useRef<Socket | null>(null);
|
||||
const [isConnected, setIsConnected] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const socketRef = useRef<Socket | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("Start of useEffect");
|
||||
@@ -28,7 +28,7 @@ export const SocketProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
console.log("Creating new socket connection");
|
||||
const newSocket = io('http://localhost:8080', {
|
||||
path: '/socket.io/',
|
||||
transports: ['websocket', 'polling'],
|
||||
transports: ['websocket'],
|
||||
withCredentials: true,
|
||||
reconnectionDelay: 1000,
|
||||
reconnectionDelayMax: 5000,
|
||||
|
||||
@@ -2,10 +2,11 @@ import React, { useState, useEffect } from "react";
|
||||
import Navbar from "../components/Layout/Navbar";
|
||||
import Button, { ToggleButton } from "../components/Layout/Button";
|
||||
import ChatPanel from "../components/Video/ChatPanel";
|
||||
import CheckoutForm, { Return } from "../components/Checkout/CheckoutForm";
|
||||
// import CheckoutForm, { Return } from "../components/Checkout/CheckoutForm";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useAuth } from "../context/AuthContext";
|
||||
import VideoPlayer from "../components/Video/VideoPlayer";
|
||||
import { SocketProvider } from "../context/SocketContext";
|
||||
|
||||
interface VideoPageProps {
|
||||
streamId: number;
|
||||
@@ -23,18 +24,16 @@ interface StreamDataProps {
|
||||
|
||||
const VideoPage: React.FC<VideoPageProps> = ({ streamId }) => {
|
||||
const { isLoggedIn } = useAuth();
|
||||
// const [showCheckout, setShowCheckout] = useState(false);
|
||||
const showReturn = window.location.search.includes("session_id");
|
||||
const { streamerName } = useParams<{ streamerName: string }>();
|
||||
const [streamData, setStreamData] = useState<StreamDataProps>();
|
||||
const navigate = useNavigate();
|
||||
|
||||
// const [showCheckout, setShowCheckout] = useState(false);
|
||||
// const showReturn = window.location.search.includes("session_id");
|
||||
// const navigate = useNavigate();
|
||||
const [isChatVisible, setIsChatVisible] = useState(false);
|
||||
const [showAuthModal, setShowAuthModal] = useState(false);
|
||||
|
||||
const toggleChat = () => {
|
||||
setIsChatVisible((prev) => !prev);
|
||||
}
|
||||
};
|
||||
|
||||
// useEffect(() => {
|
||||
// // Prevent scrolling when checkout is open
|
||||
@@ -51,7 +50,8 @@ const VideoPage: React.FC<VideoPageProps> = ({ streamId }) => {
|
||||
useEffect(() => {
|
||||
// Fetch stream data for this streamer
|
||||
fetch(
|
||||
`/api/get_stream_data/${streamerName}${streamId == 0 ? "" : `/${streamId}`
|
||||
`/api/get_stream_data/${streamerName}${
|
||||
streamId == 0 ? "" : `/${streamId}`
|
||||
}`
|
||||
).then((res) => {
|
||||
if (!res.ok) {
|
||||
@@ -73,54 +73,48 @@ const VideoPage: React.FC<VideoPageProps> = ({ streamId }) => {
|
||||
});
|
||||
}, [streamId, streamerName]);
|
||||
|
||||
useEffect(() => {
|
||||
document.body.style.overflow = showAuthModal ? "hidden" : "unset";
|
||||
|
||||
return () => {
|
||||
document.body.style.overflow = "unset"; // Cleanup
|
||||
};
|
||||
}, [showAuthModal]);
|
||||
|
||||
return (
|
||||
<div id="videoPage" className="w-full">
|
||||
<Navbar />
|
||||
|
||||
<div id="container" className="bg-gray-900">
|
||||
|
||||
<VideoPlayer streamId={streamId} />
|
||||
|
||||
<ToggleButton
|
||||
onClick={toggleChat}
|
||||
toggled={isChatVisible}
|
||||
extraClasses="absolute top-10 left-4 z-5"
|
||||
>
|
||||
{isChatVisible ? "Hide Chat" : "Show Chat"}
|
||||
</ToggleButton>
|
||||
|
||||
{isChatVisible &&
|
||||
<div id="chat" className="relative top-0 right-0 bg-gray-800 bg-opacity-75 text-white p-4 w-1/3 h-full z-10 overflow-y-auto">
|
||||
<ChatPanel streamId={streamId} />
|
||||
</div> }
|
||||
|
||||
<div
|
||||
id="stream-info"
|
||||
className="flex"
|
||||
style={{ gridArea: "3 / 1 / 4 / 2" }}
|
||||
>
|
||||
{isLoggedIn && (
|
||||
<Button
|
||||
// onClick={() => setShowCheckout(true)}
|
||||
extraClasses="mx-auto mb-4"
|
||||
<SocketProvider>
|
||||
<div id="videoPage" className="w-full">
|
||||
<Navbar />
|
||||
<div id="container" className="bg-gray-900">
|
||||
<VideoPlayer streamId={streamId} />
|
||||
<ToggleButton
|
||||
onClick={toggleChat}
|
||||
toggled={isChatVisible}
|
||||
extraClasses="z-5"
|
||||
>
|
||||
{isChatVisible ? "Hide Chat" : "Show Chat"}
|
||||
</ToggleButton>
|
||||
{isChatVisible && (
|
||||
<div
|
||||
id="chat"
|
||||
className="relative top-0 right-0 bg-gray-800 bg-opacity-75 text-white p-4 w-1/3 h-full z-10 overflow-y-auto"
|
||||
>
|
||||
Payment Screen Test
|
||||
</Button>
|
||||
<ChatPanel streamId={streamId} />
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
id="stream-info"
|
||||
className="flex"
|
||||
style={{ gridArea: "3 / 1 / 4 / 2" }}
|
||||
>
|
||||
<h1>{streamData?.streamTitle}</h1>
|
||||
<h2>{streamData?.streamerName}</h2>
|
||||
{isLoggedIn && (
|
||||
<Button
|
||||
// onClick={() => setShowCheckout(true)}
|
||||
extraClasses="mx-auto mb-4"
|
||||
>
|
||||
Payment Screen Test
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* {showCheckout && <CheckoutForm onClose={() => setShowCheckout(false)} />} */}
|
||||
{/* {showReturn && <Return />} */}
|
||||
</div>
|
||||
|
||||
{/* {showCheckout && <CheckoutForm onClose={() => setShowCheckout(false)} />} */}
|
||||
{/* {showReturn && <Return />} */}
|
||||
</div>
|
||||
</SocketProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user