k-l-lambda commited on
Commit
cccfc29
·
1 Parent(s): 5d855d2
trigo-web/app/src/composables/useSocket.ts ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ref, onUnmounted } from "vue";
2
+ import { io, Socket } from "socket.io-client";
3
+
4
+
5
+ // Singleton socket instance
6
+ let socketInstance: Socket | null = null;
7
+
8
+
9
+ export function useSocket() {
10
+ const connected = ref(false);
11
+ const error = ref<string | null>(null);
12
+
13
+
14
+ // Get or create socket instance
15
+ const getSocket = (): Socket => {
16
+ if (!socketInstance) {
17
+ // Determine the server URL based on environment
18
+ const isDev = import.meta.env?.DEV ?? (import.meta.env?.MODE === "development");
19
+ const serverUrl = isDev
20
+ ? "http://localhost:3000" // Development: backend port
21
+ : window.location.origin; // Production: same origin
22
+
23
+ socketInstance = io(serverUrl, {
24
+ autoConnect: true,
25
+ reconnection: true,
26
+ reconnectionDelay: 1000,
27
+ reconnectionAttempts: 5
28
+ });
29
+
30
+ // Connection event handlers
31
+ socketInstance.on("connect", () => {
32
+ connected.value = true;
33
+ error.value = null;
34
+ console.log("[Socket.io] Connected:", socketInstance?.id);
35
+ });
36
+
37
+ socketInstance.on("disconnect", (reason) => {
38
+ connected.value = false;
39
+ console.log("[Socket.io] Disconnected:", reason);
40
+ });
41
+
42
+ socketInstance.on("connect_error", (err) => {
43
+ error.value = err.message;
44
+ console.error("[Socket.io] Connection error:", err.message);
45
+ });
46
+ }
47
+
48
+ return socketInstance;
49
+ };
50
+
51
+
52
+ // Send echo test message
53
+ const sendEcho = (message: string): Promise<string> => {
54
+ return new Promise((resolve, reject) => {
55
+ const socket = getSocket();
56
+
57
+ if (!socket.connected) {
58
+ reject(new Error("Socket not connected"));
59
+ return;
60
+ }
61
+
62
+ // Send echo request and wait for response
63
+ socket.emit("echo", { message, timestamp: new Date().toISOString() }, (response: any) => {
64
+ if (response.error) {
65
+ reject(new Error(response.error));
66
+ } else {
67
+ resolve(response.message);
68
+ }
69
+ });
70
+
71
+ // Timeout after 5 seconds
72
+ setTimeout(() => {
73
+ reject(new Error("Echo request timeout"));
74
+ }, 5000);
75
+ });
76
+ };
77
+
78
+
79
+ // Clean up on unmount
80
+ onUnmounted(() => {
81
+ // Note: We don't disconnect the singleton instance
82
+ // It will be reused by other components
83
+ });
84
+
85
+
86
+ return {
87
+ socket: getSocket(),
88
+ connected,
89
+ error,
90
+ sendEcho
91
+ };
92
+ }
93
+
94
+
95
+ // Export function to manually disconnect (for cleanup)
96
+ export function disconnectSocket() {
97
+ if (socketInstance) {
98
+ socketInstance.disconnect();
99
+ socketInstance = null;
100
+ }
101
+ }
trigo-web/app/src/views/TrigoView.vue CHANGED
@@ -1,7 +1,7 @@
1
  <template>
2
  <div class="trigo-view">
3
  <div class="view-header">
4
- <div class="logo-container" title="K.L. Trigo">
5
  <img :src="logoImage" alt="Trigo Logo" class="app-logo" />
6
  </div>
7
  <div class="view-status">
@@ -202,6 +202,7 @@ import { Stone, validateMove, StoneType, validateTGN } from "../../../inc/trigo"
202
  import { TrigoGameFrontend } from "@/utils/TrigoGameFrontend";
203
  import { encodeAb0yz } from "../../../inc/trigo/ab0yz";
204
  import logoImage from "@/assets/logo.png";
 
205
 
206
  // Helper functions for board shape parsing
207
  const parseBoardShape = (shapeStr: string): BoardShape => {
@@ -253,6 +254,11 @@ const tgnValidationState = ref<'idle' | 'valid' | 'invalid'>('idle');
253
  const tgnValidationError = ref<string>('');
254
  let tgnValidationTimeout: ReturnType<typeof setTimeout> | null = null;
255
 
 
 
 
 
 
256
  // Canvas reference and viewport
257
  const viewportCanvas = ref<HTMLCanvasElement | null>(null);
258
  const moveHistoryContainer = ref<HTMLDivElement | null>(null);
@@ -440,6 +446,20 @@ const handleInspectGroup = (groupSize: number, liberties: number) => {
440
  };
441
 
442
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
  // Game control methods
444
  const newGame = () => {
445
  // Parse selected board shape
 
1
  <template>
2
  <div class="trigo-view">
3
  <div class="view-header">
4
+ <div class="logo-container" @click="handleLogoClick">
5
  <img :src="logoImage" alt="Trigo Logo" class="app-logo" />
6
  </div>
7
  <div class="view-status">
 
202
  import { TrigoGameFrontend } from "@/utils/TrigoGameFrontend";
203
  import { encodeAb0yz } from "../../../inc/trigo/ab0yz";
204
  import logoImage from "@/assets/logo.png";
205
+ import { useSocket } from "@/composables/useSocket";
206
 
207
  // Helper functions for board shape parsing
208
  const parseBoardShape = (shapeStr: string): BoardShape => {
 
254
  const tgnValidationError = ref<string>('');
255
  let tgnValidationTimeout: ReturnType<typeof setTimeout> | null = null;
256
 
257
+
258
+ // Socket.io connection
259
+ const { sendEcho, connected: socketConnected } = useSocket();
260
+
261
+
262
  // Canvas reference and viewport
263
  const viewportCanvas = ref<HTMLCanvasElement | null>(null);
264
  const moveHistoryContainer = ref<HTMLDivElement | null>(null);
 
446
  };
447
 
448
 
449
+ // Handle logo click - WebSocket echo test
450
+ const handleLogoClick = async () => {
451
+ try {
452
+ console.log("[Echo Test] Sending echo request...");
453
+ console.log("[Echo Test] Socket connected:", socketConnected.value);
454
+
455
+ const response = await sendEcho("Echo test from Trigo!");
456
+ console.log("[Echo Test] Response:", response);
457
+ } catch (error) {
458
+ console.error("[Echo Test] Error:", error);
459
+ }
460
+ };
461
+
462
+
463
  // Game control methods
464
  const newGame = () => {
465
  // Parse selected board shape
trigo-web/backend/src/server.ts CHANGED
@@ -46,6 +46,23 @@ app.get("/health", (_req: any, res: any) => {
46
  io.on("connection", (socket: any) => {
47
  console.log(`New client connected: ${socket.id}`);
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  socket.on("disconnect", () => {
50
  console.log(`Client disconnected: ${socket.id}`);
51
  });
 
46
  io.on("connection", (socket: any) => {
47
  console.log(`New client connected: ${socket.id}`);
48
 
49
+ // Echo test handler
50
+ socket.on("echo", (data: any, callback: any) => {
51
+ const timestamp = new Date().toISOString();
52
+ const responseMessage = `Hello from server! Received: "${data.message}" at ${timestamp}`;
53
+
54
+ console.log(`[Echo] Client ${socket.id}: ${data.message}`);
55
+
56
+ // Send response via callback
57
+ if (callback && typeof callback === "function") {
58
+ callback({
59
+ message: responseMessage,
60
+ serverTime: timestamp,
61
+ clientTime: data.timestamp
62
+ });
63
+ }
64
+ });
65
+
66
  socket.on("disconnect", () => {
67
  console.log(`Client disconnected: ${socket.id}`);
68
  });