realtimecursor
Version:
Real-time collaboration system with cursor tracking and approval workflow
172 lines • 5.83 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RealtimeCursor = void 0;
const socket_io_client_1 = require("socket.io-client");
class RealtimeCursor {
constructor(options) {
this.socket = null;
this.collaborators = [];
this.cursors = {};
this.typingUsers = new Set();
this.options = Object.assign(Object.assign({}, options), { socketUrl: options.socketUrl || options.apiUrl });
}
/**
* Connect to the real-time cursor service
*/
connect() {
if (this.socket) {
this.disconnect();
}
// Connect to socket server
this.socket = (0, socket_io_client_1.io)(this.options.socketUrl, {
auth: {
token: this.options.token
}
});
// Join project room
this.socket.emit('join-project', {
projectId: this.options.projectId,
user: {
id: this.options.user.id,
name: this.options.user.name,
color: this.options.user.color || this.getRandomColor()
}
});
// Set up event listeners
this.setupEventListeners();
}
/**
* Disconnect from the real-time cursor service
*/
disconnect() {
if (this.socket) {
this.socket.disconnect();
this.socket = null;
this.collaborators = [];
this.cursors = {};
this.typingUsers.clear();
}
}
/**
* Update cursor position
*/
updateCursor(position) {
if (!this.socket)
throw new Error('Socket not connected');
this.socket.emit('cursor-move', position);
}
/**
* Update cursor position in text
*/
updateCursorPosition(textPosition) {
if (!this.socket)
throw new Error('Socket not connected');
this.socket.emit('cursor-position', { textPosition });
}
/**
* Update content
*/
updateContent(content, cursorPosition) {
if (!this.socket)
throw new Error('Socket not connected');
this.socket.emit('content-change', { content, cursorPosition });
}
/**
* Set typing indicator
*/
setTyping(isTyping) {
if (!this.socket)
throw new Error('Socket not connected');
this.socket.emit('user-typing', { isTyping });
}
/**
* Register event handlers
*/
setupEventListeners() {
if (!this.socket)
return;
this.socket.on('room-users', (users) => {
var _a;
this.collaborators = users;
(_a = this.onCollaboratorsChange) === null || _a === void 0 ? void 0 : _a.call(this, users);
});
this.socket.on('user-joined', ({ user }) => {
var _a, _b;
this.collaborators.push(user);
(_a = this.onCollaboratorsChange) === null || _a === void 0 ? void 0 : _a.call(this, this.collaborators);
(_b = this.onUserJoined) === null || _b === void 0 ? void 0 : _b.call(this, user);
});
this.socket.on('user-left', ({ socketId }) => {
var _a, _b;
this.collaborators = this.collaborators.filter(u => u.socketId !== socketId);
delete this.cursors[socketId];
this.typingUsers.delete(socketId);
(_a = this.onCollaboratorsChange) === null || _a === void 0 ? void 0 : _a.call(this, this.collaborators);
(_b = this.onUserLeft) === null || _b === void 0 ? void 0 : _b.call(this, { socketId });
});
this.socket.on('content-update', (data) => {
var _a;
(_a = this.onContentUpdate) === null || _a === void 0 ? void 0 : _a.call(this, data);
});
this.socket.on('cursor-update', (data) => {
var _a;
const { socketId, user, x, y, textPosition } = data;
this.cursors[socketId] = { x, y, user, textPosition };
(_a = this.onCursorUpdate) === null || _a === void 0 ? void 0 : _a.call(this, data);
});
this.socket.on('user-typing', ({ socketId, isTyping }) => {
var _a;
if (isTyping) {
this.typingUsers.add(socketId);
}
else {
this.typingUsers.delete(socketId);
}
(_a = this.onTypingStatusChange) === null || _a === void 0 ? void 0 : _a.call(this, Array.from(this.typingUsers));
});
this.socket.on('cursor-position', (data) => {
var _a;
const { socketId, textPosition, user } = data;
if (this.cursors[socketId]) {
this.cursors[socketId].textPosition = textPosition;
this.cursors[socketId].user = user;
}
else {
this.cursors[socketId] = { textPosition, user };
}
(_a = this.onCursorPositionUpdate) === null || _a === void 0 ? void 0 : _a.call(this, data);
});
}
/**
* Get random color for cursor
*/
getRandomColor() {
const colors = [
'#3b82f6', '#ef4444', '#10b981', '#f59e0b',
'#8b5cf6', '#06b6d4', '#f97316', '#84cc16',
'#ec4899', '#6366f1', '#14b8a6', '#f43f5e'
];
return colors[Math.floor(Math.random() * colors.length)];
}
/**
* Get current collaborators
*/
getCollaborators() {
return this.collaborators;
}
/**
* Get current cursors
*/
getCursors() {
return this.cursors;
}
/**
* Get typing users
*/
getTypingUsers() {
return Array.from(this.typingUsers);
}
}
exports.RealtimeCursor = RealtimeCursor;
exports.default = RealtimeCursor;
//# sourceMappingURL=realtimecursor.js.map