feat: RefBoard v0.4.0 — collaborative reference board with layers, groups & polished UI

Full-featured PureRef-style collaborative canvas for game dev teams:
- Layer panel with visibility, lock, drag reorder, group/ungroup (Ctrl+G/Shift+G)
- Arrangement tools (grid, row, column) via right-click context menu
- Copy to system clipboard (Ctrl+C writes PNG for external paste in Paint etc.)
- Number shortcuts (1-5) for tool selection with visible shortcut badges
- Premium dark UI across all pages (Login, Collections, Boards, Editor)
- Socket.IO rooms for cursors, transforms, and presence notifications
- MinIO image storage with backend proxy, drag/drop and paste upload
This commit is contained in:
Hiren
2026-03-09 13:57:49 +05:30
commit e47777d237
43 changed files with 10276 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
const { Server } = require('socket.io');
const { verifyToken } = require('../auth');
const { getUserById } = require('../db');
const { setupBoardRoom } = require('./board-room');
/**
* Set up Socket.IO on the given HTTP server.
* Returns the io instance.
*/
function setupSocket(httpServer) {
const io = new Server(httpServer, {
cors: {
origin: process.env.CORS_ORIGIN || '*',
methods: ['GET', 'POST'],
},
pingInterval: 25000,
pingTimeout: 60000,
});
// JWT authentication middleware
io.use((socket, next) => {
try {
const token = socket.handshake.auth?.token;
if (!token) {
return next(new Error('Authentication required'));
}
const decoded = verifyToken(token);
const user = getUserById(decoded.id);
if (!user) {
return next(new Error('User not found'));
}
// Store user info on socket
socket.userId = user.id;
socket.userEmail = user.email;
socket.userDisplayName = user.display_name;
socket.userRole = user.role;
next();
} catch (err) {
next(new Error('Invalid token'));
}
});
// Handle connections
io.on('connection', (socket) => {
console.log(`[socket] User connected: ${socket.userDisplayName} (${socket.userId})`);
// Set up board room handlers
setupBoardRoom(io, socket);
socket.on('disconnect', (reason) => {
console.log(`[socket] User disconnected: ${socket.userDisplayName} (${reason})`);
});
});
return io;
}
module.exports = { setupSocket };