-
${r.id}
-
${r.peerCount} peers
+
+
+ ${escapeHtml(r.id)}
+ ${r.hasPassword ? '🔒' : ''}
+
+
${parseInt(r.peerCount)} peers
`).join('');
@@ -232,6 +259,19 @@ elements.filterNoise.addEventListener('change', () => {
});
});
+elements.serverUrl.addEventListener('input', () => {
+ chrome.storage.sync.set({ serverUrl: elements.serverUrl.value });
+});
+
+elements.serverUrl.addEventListener('change', () => {
+ let url = elements.serverUrl.value.trim();
+ if (url && !url.includes('://')) {
+ url = 'ws://' + url;
+ elements.serverUrl.value = url;
+ chrome.storage.sync.set({ serverUrl: url });
+ }
+});
+
elements.tabs.forEach(btn => {
btn.addEventListener('click', () => {
elements.tabs.forEach(b => b.classList.remove('active'));
diff --git a/server/index.js b/server/index.js
index c6d8dad..1c85d36 100644
--- a/server/index.js
+++ b/server/index.js
@@ -178,6 +178,7 @@ io.on('connection', (socket) => {
passwordHash,
peers: new Set(),
peerIds: new Map(),
+ peerData: new Map(), // socketId -> { peerId, tabTitle }
lastActivity: Date.now()
};
rooms.set(roomId, room);
@@ -199,12 +200,13 @@ io.on('connection', (socket) => {
socket.join(roomId);
room.peers.add(socket.id);
room.peerIds.set(socket.id, peerId);
+ room.peerData.set(socket.id, { peerId, tabTitle: null });
socketToRoom.set(socket.id, { roomId, peerId });
socket.to(roomId).emit(EVENTS.PEER_STATUS, { peerId, status: 'joined' });
socket.emit(EVENTS.ROOM_DATA, {
roomId,
- peers: Array.from(room.peers).map(sid => room.peerIds.get(sid))
+ peers: Array.from(room.peers).map(sid => room.peerData.get(sid))
});
log('ROOM', `Peer ${peerId} joined: ${roomId}`);
} catch (err) {
@@ -231,7 +233,13 @@ io.on('connection', (socket) => {
const mapping = socketToRoom.get(socket.id);
if (mapping) {
const room = rooms.get(mapping.roomId);
- if (room) room.lastActivity = Date.now();
+ if (room) {
+ room.lastActivity = Date.now();
+ // Update metadata if it's a peer_status (heartbeat)
+ if (eventName === EVENTS.PEER_STATUS && data.tabTitle) {
+ room.peerData.set(socket.id, { peerId: mapping.peerId, tabTitle: data.tabTitle });
+ }
+ }
socket.to(mapping.roomId).emit(eventName, { ...data, senderId: mapping.peerId });
}
});
@@ -240,7 +248,8 @@ io.on('connection', (socket) => {
socket.on(EVENTS.GET_ROOMS, () => {
const list = Array.from(rooms.entries()).map(([id, r]) => ({
id,
- peerCount: r.peers.size
+ peerCount: r.peers.size,
+ hasPassword: !!r.passwordHash
}));
socket.emit(EVENTS.ROOM_LIST, { rooms: list });
});
@@ -254,6 +263,7 @@ io.on('connection', (socket) => {
if (room) {
room.peers.delete(socket.id);
room.peerIds.delete(socket.id);
+ room.peerData.delete(socket.id);
socket.to(roomId).emit(EVENTS.PEER_STATUS, { peerId, status: 'left' });
if (room.peers.size === 0) {
rooms.delete(roomId);
@@ -273,6 +283,7 @@ io.on('connection', (socket) => {
if (room) {
room.peers.delete(socket.id);
room.peerIds.delete(socket.id);
+ room.peerData.delete(socket.id);
socket.to(roomId).emit(EVENTS.PEER_STATUS, { peerId, status: 'left' });
if (room.peers.size === 0) {
rooms.delete(roomId);
diff --git a/shared/constants.js b/shared/constants.js
index 7e7c1f1..2e3da01 100644
--- a/shared/constants.js
+++ b/shared/constants.js
@@ -7,7 +7,7 @@ export const APP_VERSION = "1.0.0";
export const OFFICIAL_SERVER_URL = 'wss://sync.shik3i.net';
export const OFFICIAL_LANDING_PAGE_URL = 'https://koalasync.shik3i.net';
-export const OFFICIAL_SERVER_TOKEN = 'koala_secure_access_2026';
+export const OFFICIAL_SERVER_TOKEN = '62170b705234c4f4807a9b22420bb93cf1a2aacfa4c5d3b47804482babb8eb50';
export const EVENTS = {
// Connection & Room