100 lines
3.5 KiB
JavaScript
100 lines
3.5 KiB
JavaScript
import { useEffect, useState, useCallback } from 'react';
|
|
import io from "socket.io-client";
|
|
import { SERVER_BASE_URL } from './App';
|
|
import { MousingLayer } from './MousingLayer';
|
|
import { SettingsModal } from './SettingsModal';
|
|
import { UserList } from './UserList';
|
|
import { ProgressBar } from './ProgressBar';
|
|
import { ChatInput } from './ChatInput';
|
|
import { MessageList } from './MessageList';
|
|
|
|
export function Chat({ user, updateUser, theme, setTheme }) {
|
|
|
|
var [messages, setMessages] = useState([]);
|
|
var [users, setUsers] = useState([]);
|
|
var [socket, setSocket] = useState();
|
|
var [settingsModalOpen, setSettingsModalOpen] = useState(false);
|
|
var [progress, setProgress] = useState(null);
|
|
var [mice, setMice] = useState({});
|
|
var [unread, setUnread] = useState(0);
|
|
|
|
useEffect(() => {
|
|
document.getElementById("favicon").href = SERVER_BASE_URL + `/favicon.svg?num=${unread}`;
|
|
}, [unread]);
|
|
|
|
useEffect(() => {
|
|
var fn = () => {
|
|
if (document.visibilityState === "visible") setUnread(0);
|
|
};
|
|
document.addEventListener("visibilitychange", fn);
|
|
return () => document.removeEventListener("visibilitychange", fn);
|
|
}, []);
|
|
|
|
|
|
var loadMessages = useCallback(function loadMessages() {
|
|
fetch(SERVER_BASE_URL + "/messages?secret=" + user.secret).then(res => res.json()).then(messages => {
|
|
console.debug("messages", messages);
|
|
setMessages(messages);
|
|
});
|
|
}, [setMessages, user.secret]);
|
|
|
|
useEffect(() => {
|
|
var socket = io(SERVER_BASE_URL, {
|
|
transports: ["websocket", "polling"]
|
|
});
|
|
setSocket(socket);
|
|
global.socket = socket;
|
|
socket.on("connect", () => {
|
|
console.debug("socket connect, id: " + socket.id);
|
|
socket.emit("user", user);
|
|
});
|
|
socket.on("disconnect", () => console.debug("socket disconnect"));
|
|
/*{let emit = socket.emit; socket.emit = function() {
|
|
emit.apply(socket, arguments);
|
|
console.debug("send", ...arguments);
|
|
}}
|
|
socket.onAny((eventName, ...args) => {
|
|
console.debug("receive", eventName, ...args)
|
|
});*/
|
|
socket.on("messages", setMessages);
|
|
socket.on("message", message => {
|
|
setMessages(messages => [...messages, message]);
|
|
if (document.visibilityState === "hidden") setUnread(unread => ++unread);
|
|
});
|
|
socket.on("users", setUsers);
|
|
window.onmousemove = event => {
|
|
socket.emit("mouse", event.pageX / window.innerWidth, event.pageY / window.innerHeight);
|
|
};
|
|
socket.on("mouse", (x, y, socketid) => {
|
|
setMice(mice => ({ ...mice, [socketid]: { x, y } }));
|
|
});
|
|
return () => socket.close();
|
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
useEffect(() => {
|
|
socket?.emit("user", user);
|
|
}, [socket, user]);
|
|
|
|
useEffect(() => {
|
|
var socketids = users.map(user => user.socketid);
|
|
setMice(mice => {
|
|
for (let mouseid in mice) if (!socketids.includes(mouseid)) delete mice[mouseid];
|
|
return mice;
|
|
});
|
|
}, [users]);
|
|
|
|
var sendMessage = useCallback(message => socket.emit("message", message), [socket]);
|
|
|
|
|
|
return (
|
|
<div className="Chat flex flex-col">
|
|
<MessageList messages={messages} setMessages={setMessages} userSecret={user.secret} />
|
|
<UserList users={users} updateUser={updateUser} user={user} socket={socket} />
|
|
<ProgressBar progress={progress} />
|
|
<ChatInput sendMessage={sendMessage} user={user} updateUser={updateUser} setSettingsModalOpen={setSettingsModalOpen} socket={socket} setProgress={setProgress} />
|
|
<SettingsModal open={settingsModalOpen} setOpen={setSettingsModalOpen} user={user} updateUser={updateUser} theme={theme} setTheme={setTheme} />
|
|
<MousingLayer mice={mice} users={users} />
|
|
</div>
|
|
);
|
|
}
|