Skip to content

Commit 5329de4

Browse files
committed
feat: add multi-tab support for a single user
1 parent ca0a5a4 commit 5329de4

File tree

4 files changed

+272
-128
lines changed

4 files changed

+272
-128
lines changed

apps/collabydraw/canvas-engine/CanvasEngine.ts

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ import type { Point } from "roughjs/bin/geometry";
4444
import { getFontSize, getLineHeight } from "@/utils/textUtils";
4545
import { generateFreeDrawPath } from "./RenderElements";
4646

47+
type WebSocketConnection = {
48+
connectionId: string;
49+
connected: boolean;
50+
};
51+
4752
export class CanvasEngine {
4853
private canvas: HTMLCanvasElement;
4954
private ctx: CanvasRenderingContext2D;
@@ -96,6 +101,9 @@ export class CanvasEngine {
96101

97102
private roughSeed: number = 1;
98103

104+
private connectionId: string | null = null;
105+
private myConnections: WebSocketConnection[] = [];
106+
99107
constructor(
100108
canvas: HTMLCanvasElement,
101109
roomId: string | null,
@@ -180,17 +188,35 @@ export class CanvasEngine {
180188
this.socket.onmessage = async (event) => {
181189
try {
182190
const data: WebSocketMessage = JSON.parse(event.data);
191+
if (data.type === WsDataType.CONNECTION_READY) {
192+
this.connectionId = data.connectionId;
193+
console.log(`Assigned connection ID: ${this.connectionId}`);
194+
}
183195

184196
switch (data.type) {
185197
case WsDataType.USER_JOINED:
198+
if (
199+
data.userId === this.userId &&
200+
data.connectionId !== this.connectionId
201+
) {
202+
this.myConnections.push({
203+
connectionId: data.connectionId,
204+
connected: true,
205+
});
206+
console.log(`🔁 Another tab detected: ${data.connectionId}`);
207+
}
186208
if (data.participants && Array.isArray(data.participants)) {
187209
this.participants = data.participants;
188210
this.onParticipantsUpdate?.(this.participants);
189211
}
190-
191212
break;
192213

193214
case WsDataType.USER_LEFT:
215+
if (data.userId === this.userId && data.connectionId) {
216+
this.myConnections = this.myConnections.filter(
217+
(c) => c.connectionId !== data.connectionId
218+
);
219+
}
194220
if (data.userId) {
195221
this.participants = this.participants.filter(
196222
(u) => u.userId !== data.userId
@@ -225,7 +251,20 @@ export class CanvasEngine {
225251

226252
case WsDataType.DRAW:
227253
case WsDataType.UPDATE:
228-
if (data.userId !== this.userId && data.message) {
254+
if (
255+
data.userId === this.userId &&
256+
data.connectionId !== this.connectionId
257+
) {
258+
if (data.message) {
259+
const decrypted = await decryptData(
260+
data.message,
261+
this.encryptionKey!
262+
);
263+
const shape = JSON.parse(decrypted);
264+
this.updateShapes([shape]);
265+
this.notifyShapeCountChange();
266+
}
267+
} else if (data.userId !== this.userId && data.message) {
229268
const decrypted = await decryptData(
230269
data.message,
231270
this.encryptionKey!
@@ -237,7 +276,14 @@ export class CanvasEngine {
237276
break;
238277

239278
case WsDataType.ERASER:
240-
if (data.userId !== this.userId && data.id) {
279+
if (
280+
data.userId === this.userId &&
281+
data.connectionId !== this.connectionId
282+
) {
283+
if (data.id) {
284+
this.removeShape(data.id);
285+
}
286+
} else if (data.userId !== this.userId && data.id) {
241287
this.removeShape(data.id);
242288
}
243289
break;
@@ -306,6 +352,7 @@ export class CanvasEngine {
306352
userName: this.userName!,
307353
timestamp: new Date().toISOString(),
308354
participants: null,
355+
connectionId: this.connectionId!,
309356
});
310357
}
311358
}
@@ -628,6 +675,7 @@ export class CanvasEngine {
628675
userName: this.userName!,
629676
timestamp: new Date().toISOString(),
630677
participants: null,
678+
connectionId: this.connectionId!,
631679
});
632680
console.error("Error sending shape update ws message", e);
633681
}
@@ -795,6 +843,7 @@ export class CanvasEngine {
795843
type: WsDataType.UPDATE,
796844
id: shape.id,
797845
message: JSON.stringify(shape),
846+
connectionId: this.connectionId!,
798847
roomId: this.roomId,
799848
userId: this.userId!,
800849
userName: this.userName!,
@@ -1848,6 +1897,7 @@ export class CanvasEngine {
18481897
userName: this.userName!,
18491898
timestamp: new Date().toISOString(),
18501899
participants: null,
1900+
connectionId: this.connectionId!,
18511901
});
18521902
console.error("Error sending shape update ws message", e);
18531903
}

apps/collabydraw/components/SignupWelcomeButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export default function SignupWelcomeButton() {
99
session?.user.id ? (
1010
<></>
1111
) : (
12-
<Link className="welcome-screen-menu-item " href="/auth/signup">
12+
<Link className="welcome-screen-menu-item " href="/auth/signin">
1313
<div className="welcome-screen-menu-item__icon">
1414
<svg aria-hidden="true" focusable="false" role="img" viewBox="0 0 24 24" className="" fill="none" strokeWidth="2" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round">
1515
<g strokeWidth="1.5">

0 commit comments

Comments
 (0)