File size: 3,365 Bytes
9bff0af
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
const express = require("express");
const http = require("http");
const { Server } = require("socket.io");
const cors = require("cors");

const app = express();
app.use(cors());
app.use(express.json());

app.get("/health", (req, res) => res.json({ status: "ok", uptime: process.uptime() }));

const server = http.createServer(app);

const io = new Server(server, {
  cors: { origin: "*", methods: ["GET", "POST"] },
});

const rooms = {};

function getRoom(roomId) {
  if (!rooms[roomId]) {
    rooms[roomId] = {
      users: {},
      canvasElements: [],
      code: { content: "// Start coding together...\n", language: "javascript" },
      messages: [],
    };
  }
  return rooms[roomId];
}

io.on("connection", (socket) => {
  let currentRoom = null;
  let currentUser = null;

  socket.on("join-room", ({ roomId, user }) => {
    currentRoom = roomId;
    currentUser = { ...user, socketId: socket.id };
    socket.join(roomId);

    const room = getRoom(roomId);
    room.users[socket.id] = currentUser;

    socket.emit("room-state", {
      canvasElements: room.canvasElements,
      code: room.code,
      messages: room.messages,
      users: Object.values(room.users),
    });

    socket.to(roomId).emit("user-joined", currentUser);
    io.to(roomId).emit("room-users", Object.values(room.users));
    console.log(`[${roomId}] ${user.name} joined`);
  });

  socket.on("canvas-elements", (elements) => {
    if (!currentRoom) return;
    rooms[currentRoom].canvasElements = elements;
    socket.to(currentRoom).emit("canvas-elements", elements);
  });

  socket.on("canvas-clear", () => {
    if (!currentRoom) return;
    rooms[currentRoom].canvasElements = [];
    io.to(currentRoom).emit("canvas-clear");
  });

  socket.on("code-change", ({ content, language }) => {
    if (!currentRoom) return;
    rooms[currentRoom].code = { content, language };
    socket.to(currentRoom).emit("code-update", { content, language });
  });

  socket.on("cursor-move", ({ x, y }) => {
    if (!currentRoom || !currentUser) return;
    socket.to(currentRoom).emit("cursor-update", {
      socketId: socket.id,
      name: currentUser.name,
      color: currentUser.color,
      x,
      y,
    });
  });

  socket.on("send-message", (msg) => {
    if (!currentRoom) return;
    const fullMsg = { ...msg, id: Date.now().toString() };
    rooms[currentRoom].messages.push(fullMsg);
    if (rooms[currentRoom].messages.length > 200) {
      rooms[currentRoom].messages = rooms[currentRoom].messages.slice(-200);
    }
    io.to(currentRoom).emit("receive-message", fullMsg);
  });

  socket.on("disconnect", () => {
    if (!currentRoom) return;
    const room = rooms[currentRoom];
    if (!room) return;
    delete room.users[socket.id];
    io.to(currentRoom).emit("user-left", socket.id);
    io.to(currentRoom).emit("room-users", Object.values(room.users));
    if (Object.keys(room.users).length === 0) {
      setTimeout(() => {
        if (rooms[currentRoom] && Object.keys(rooms[currentRoom].users).length === 0) {
          delete rooms[currentRoom];
          console.log(`[${currentRoom}] Room closed (empty)`);
        }
      }, 300000);
    }
    console.log(`[${currentRoom}] ${currentUser?.name || socket.id} left`);
  });
});

const PORT = process.env.PORT || 3001;
server.listen(PORT, () => console.log(`Canvas2Code server running on :${PORT}`));