first commit
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
// Whiteboard WebSocket Store mit Svelte 5 Runes
|
||||
import { io, Socket } from 'socket.io-client';
|
||||
|
||||
export interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
export type DrawingTool = 'pen' | 'eraser' | 'line' | 'rectangle' | 'circle' | 'text';
|
||||
|
||||
export interface DrawingData {
|
||||
id: string;
|
||||
whiteboardId: string;
|
||||
tool: DrawingTool;
|
||||
points: Point[];
|
||||
color?: string;
|
||||
lineWidth?: number;
|
||||
text?: string;
|
||||
userId: string;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface RemoteCursor {
|
||||
userId: string;
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
class WhiteboardStore {
|
||||
socket: Socket | null = null;
|
||||
connected = $state(false);
|
||||
whiteboardId = $state<string>('default-room');
|
||||
userId = $state<string>('');
|
||||
activeUsers = $state<string[]>([]);
|
||||
remoteCursors = $state<Map<string, RemoteCursor>>(new Map());
|
||||
drawings = $state<DrawingData[]>([]);
|
||||
|
||||
connect(whiteboardId: string, userId: string) {
|
||||
this.whiteboardId = whiteboardId;
|
||||
this.userId = userId;
|
||||
|
||||
// WebSocket-Verbindung herstellen
|
||||
this.socket = io('http://localhost:3000/whiteboard', {
|
||||
withCredentials: true,
|
||||
transports: ['websocket', 'polling']
|
||||
});
|
||||
|
||||
this.setupEventListeners();
|
||||
|
||||
// Dem Whiteboard beitreten
|
||||
this.socket.emit('join-whiteboard', {
|
||||
whiteboardId,
|
||||
userId
|
||||
});
|
||||
}
|
||||
|
||||
private setupEventListeners() {
|
||||
if (!this.socket) return;
|
||||
|
||||
this.socket.on('connect', () => {
|
||||
console.log('✅ Connected to whiteboard');
|
||||
this.connected = true;
|
||||
});
|
||||
|
||||
this.socket.on('disconnect', () => {
|
||||
console.log('❌ Disconnected from whiteboard');
|
||||
this.connected = false;
|
||||
});
|
||||
|
||||
// Empfange aktuelle Whiteboard-Daten
|
||||
this.socket.on('whiteboard-state', (drawings: DrawingData[]) => {
|
||||
console.log('📥 Received whiteboard state:', drawings.length, 'drawings');
|
||||
this.drawings = drawings;
|
||||
});
|
||||
|
||||
// Empfange neue Zeichnungen von anderen Benutzern
|
||||
this.socket.on('drawing', (drawing: DrawingData) => {
|
||||
console.log('🎨 Received drawing from user:', drawing.userId);
|
||||
this.drawings = [...this.drawings, drawing];
|
||||
});
|
||||
|
||||
// Benutzer ist beigetreten
|
||||
this.socket.on('user-joined', (data: { userId: string; activeUsers: string[] }) => {
|
||||
console.log('👋 User joined:', data.userId);
|
||||
this.activeUsers = data.activeUsers;
|
||||
});
|
||||
|
||||
// Benutzer hat verlassen
|
||||
this.socket.on('user-left', (data: { userId: string; activeUsers: string[] }) => {
|
||||
console.log('👋 User left:', data.userId);
|
||||
this.activeUsers = data.activeUsers;
|
||||
// Entferne Cursor des Benutzers
|
||||
this.remoteCursors.delete(data.userId);
|
||||
});
|
||||
|
||||
// Whiteboard wurde gelöscht
|
||||
this.socket.on('whiteboard-cleared', (data: { userId: string }) => {
|
||||
console.log('🗑️ Whiteboard cleared by:', data.userId);
|
||||
this.drawings = [];
|
||||
});
|
||||
|
||||
// Cursor-Position von anderen Benutzern
|
||||
this.socket.on('cursor-position', (data: { userId: string; x: number; y: number }) => {
|
||||
this.remoteCursors.set(data.userId, {
|
||||
userId: data.userId,
|
||||
x: data.x,
|
||||
y: data.y
|
||||
});
|
||||
// Trigger reaktivität
|
||||
this.remoteCursors = new Map(this.remoteCursors);
|
||||
});
|
||||
|
||||
// Undo wurde angefordert
|
||||
this.socket.on('undo-requested', (data: { userId: string }) => {
|
||||
console.log('↩️ Undo requested by:', data.userId);
|
||||
// Hier könnte man Undo-Logik implementieren
|
||||
});
|
||||
}
|
||||
|
||||
sendDrawing(tool: DrawingTool, points: Point[], color: string, lineWidth: number, text?: string, id?: string) {
|
||||
if (!this.socket || !this.connected) {
|
||||
console.error('❌ Not connected to whiteboard');
|
||||
return;
|
||||
}
|
||||
|
||||
const drawingData: DrawingData = {
|
||||
id: id || `${Date.now()}-${Math.random()}`,
|
||||
whiteboardId: this.whiteboardId,
|
||||
tool,
|
||||
points,
|
||||
color,
|
||||
lineWidth,
|
||||
text,
|
||||
userId: this.userId,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
console.log('📤 Sending drawing:', tool, 'points:', points.length);
|
||||
|
||||
// Füge die Zeichnung sofort lokal hinzu (optimistische Update)
|
||||
this.drawings = [...this.drawings, drawingData];
|
||||
|
||||
// Sende an den Server (wird nur an andere Clients weitergeleitet)
|
||||
this.socket.emit('draw', drawingData);
|
||||
}
|
||||
|
||||
clearWhiteboard() {
|
||||
if (!this.socket || !this.connected) {
|
||||
console.error('❌ Not connected to whiteboard');
|
||||
return;
|
||||
}
|
||||
|
||||
this.socket.emit('clear-whiteboard', {
|
||||
whiteboardId: this.whiteboardId,
|
||||
userId: this.userId
|
||||
});
|
||||
|
||||
// Lösche lokal
|
||||
this.drawings = [];
|
||||
}
|
||||
|
||||
sendCursorPosition(x: number, y: number) {
|
||||
if (!this.socket || !this.connected) return;
|
||||
|
||||
this.socket.emit('cursor-move', {
|
||||
whiteboardId: this.whiteboardId,
|
||||
userId: this.userId,
|
||||
x,
|
||||
y
|
||||
});
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
if (this.socket) {
|
||||
this.socket.disconnect();
|
||||
this.socket = null;
|
||||
}
|
||||
this.connected = false;
|
||||
this.activeUsers = [];
|
||||
this.remoteCursors = new Map();
|
||||
this.drawings = [];
|
||||
}
|
||||
}
|
||||
|
||||
export const whiteboardStore = new WhiteboardStore();
|
||||
Reference in New Issue
Block a user