Added back Remote Cursors
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Server as SocketIOServer, Socket } from 'socket.io';
|
||||
import { upsertPixels, getAllPixels, db } from './database';
|
||||
import { upsertPixelsWithConflictResolution, getAllPixels, db, validatePixel } from './database';
|
||||
import { Cursor, Pixel } from '../shared/types';
|
||||
import passport from 'passport';
|
||||
|
||||
@@ -18,7 +18,19 @@ interface UserSocket extends Socket {
|
||||
user?: any;
|
||||
}
|
||||
|
||||
// Helper function to get user data from db
|
||||
interface PaintRequest {
|
||||
pixels: Pixel[];
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
interface PaintAck {
|
||||
success: boolean;
|
||||
saved: number;
|
||||
conflicts: number;
|
||||
pixels?: Pixel[];
|
||||
message?: string;
|
||||
}
|
||||
|
||||
function getUserById(userId: number) {
|
||||
try {
|
||||
const stmt = db.prepare('SELECT * FROM users WHERE id = ?');
|
||||
@@ -30,7 +42,7 @@ function getUserById(userId: number) {
|
||||
}
|
||||
|
||||
export function setupSocketIO(io: SocketIOServer): void {
|
||||
const connectedUsers = new Map<string, { x: number; y: number; color: string; username: string; userId: number }>();
|
||||
const connectedUsers = new Map<string, { x: number; y: number; color: string; username: string; userId: string }>();
|
||||
|
||||
io.on('connection', (socket: Socket) => {
|
||||
const userSocket = socket as UserSocket;
|
||||
@@ -75,18 +87,52 @@ export function setupSocketIO(io: SocketIOServer): void {
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('paint-pixels', async (pixels: Pixel[]) => {
|
||||
socket.on('paint-pixels', async (request: PaintRequest, callback: (ack: PaintAck) => void) => {
|
||||
try {
|
||||
if (!userSocket.user) {
|
||||
socket.emit('error', 'Authentication required to paint pixels');
|
||||
const ack: PaintAck = { success: false, saved: 0, conflicts: 0, message: 'Authentication required' };
|
||||
callback(ack);
|
||||
return;
|
||||
}
|
||||
|
||||
upsertPixels(pixels);
|
||||
socket.broadcast.emit('canvas-update', { pixels });
|
||||
const { pixels, timestamp } = request;
|
||||
|
||||
if (!Array.isArray(pixels) || pixels.length === 0) {
|
||||
const ack: PaintAck = { success: false, saved: 0, conflicts: 0, message: 'Invalid pixels data' };
|
||||
callback(ack);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const pixel of pixels) {
|
||||
const validationError = validatePixel(pixel);
|
||||
if (validationError) {
|
||||
const ack: PaintAck = { success: false, saved: 0, conflicts: 0, message: validationError };
|
||||
callback(ack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const userIdNum = typeof userData.id === 'number' ? userData.id : parseInt(userData.id, 10);
|
||||
const result = upsertPixelsWithConflictResolution(
|
||||
pixels.map(p => ({ ...p, userId: userIdNum })),
|
||||
timestamp || 0
|
||||
);
|
||||
|
||||
if (result.saved > 0) {
|
||||
socket.broadcast.emit('canvas-update', { pixels });
|
||||
}
|
||||
|
||||
const ack: PaintAck = {
|
||||
success: true,
|
||||
saved: result.saved,
|
||||
conflicts: result.conflicts,
|
||||
pixels: result.conflicts > 0 ? pixels : undefined
|
||||
};
|
||||
callback(ack);
|
||||
} catch (error) {
|
||||
console.error('Error saving pixels:', error);
|
||||
socket.emit('error', 'Failed to save pixels');
|
||||
const ack: PaintAck = { success: false, saved: 0, conflicts: 0, message: 'Failed to save pixels' };
|
||||
callback(ack);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user