mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-07-26 12:08:15 +00:00
UI: Context-aware layouts and Smart Invite links (Server-in-URL)
This commit is contained in:
+51
-33
@@ -205,41 +205,59 @@
|
||||
|
||||
<!-- Room Tab -->
|
||||
<div id="tab-room" class="tab-content active">
|
||||
<div class="form-group">
|
||||
<label>Server</label>
|
||||
<div style="display:flex; gap:4px; margin-bottom:8px;">
|
||||
<button id="serverOfficial" class="tab-btn active" style="flex:1; padding:6px; font-size:11px;">Official</button>
|
||||
<button id="serverCustom" class="tab-btn" style="flex:1; padding:6px; font-size:11px;">Custom</button>
|
||||
<!-- JOIN SECTION: Visible when not in a room -->
|
||||
<div id="section-join">
|
||||
<div class="form-group">
|
||||
<label>Server</label>
|
||||
<div style="display:flex; gap:4px; margin-bottom:8px;">
|
||||
<button id="serverOfficial" class="tab-btn active" style="flex:1; padding:6px; font-size:11px;">Official</button>
|
||||
<button id="serverCustom" class="tab-btn" style="flex:1; padding:6px; font-size:11px;">Custom</button>
|
||||
</div>
|
||||
<input type="text" id="serverUrl" placeholder="wss://your-server:3000" style="display:none;">
|
||||
</div>
|
||||
<input type="text" id="serverUrl" placeholder="wss://your-server:3000" style="display:none;">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Room ID</label>
|
||||
<input type="text" id="roomId" placeholder="Leave empty to create">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Password (Optional)</label>
|
||||
<input type="password" id="password" placeholder="Room password">
|
||||
</div>
|
||||
<div id="roomError" style="display:none; color:var(--error); font-size:11px; margin-bottom:8px; text-align:center;"></div>
|
||||
<button id="joinBtn" class="primary">Join Room</button>
|
||||
<button id="createRoomBtn" class="secondary" style="border: 1px solid var(--accent); color: var(--accent);">Create Random Room</button>
|
||||
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 1.5rem; margin-bottom: 8px;">
|
||||
<label style="margin:0;">Public Rooms</label>
|
||||
<button id="refreshRooms" style="background:transparent; border:none; color:var(--accent); font-size:10px; cursor:pointer;">REFRESH</button>
|
||||
</div>
|
||||
<div id="publicRooms" class="info-card" style="max-height: 120px; overflow-y: auto; padding: 4px;">
|
||||
<div style="text-align:center; color: var(--text-muted); font-size: 11px; padding: 10px;">Refreshing...</div>
|
||||
</div>
|
||||
|
||||
<div id="roomInfo" style="display:none; margin-top: 20px;">
|
||||
<label>Invite Link</label>
|
||||
<div class="invite-box">
|
||||
<input type="text" id="inviteLink" readonly>
|
||||
<button id="copyInvite" class="secondary">📋</button>
|
||||
<div class="form-group">
|
||||
<label>Room ID</label>
|
||||
<input type="text" id="roomId" placeholder="Leave empty to create">
|
||||
</div>
|
||||
<button id="leaveBtn" class="secondary" style="color: var(--error);">Leave Room</button>
|
||||
<div class="form-group">
|
||||
<label>Password (Optional)</label>
|
||||
<input type="password" id="password" placeholder="Room password">
|
||||
</div>
|
||||
<div id="roomError" style="display:none; color:var(--error); font-size:11px; margin-bottom:8px; text-align:center;"></div>
|
||||
<button id="joinBtn" class="primary">Join Room</button>
|
||||
<button id="createRoomBtn" class="secondary" style="border: 1px solid var(--accent); color: var(--accent);">Create Random Room</button>
|
||||
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 1.5rem; margin-bottom: 8px;">
|
||||
<label style="margin:0;">Public Rooms</label>
|
||||
<button id="refreshRooms" style="background:transparent; border:none; color:var(--accent); font-size:10px; cursor:pointer;">REFRESH</button>
|
||||
</div>
|
||||
<div id="publicRooms" class="info-card" style="max-height: 120px; overflow-y: auto; padding: 4px;">
|
||||
<div style="text-align:center; color: var(--text-muted); font-size: 11px; padding: 10px;">Refreshing...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ACTIVE SECTION: Visible when in a room -->
|
||||
<div id="section-active" style="display:none;">
|
||||
<div class="info-card" style="margin-bottom: 20px;">
|
||||
<label>Invite Link</label>
|
||||
<div class="invite-box">
|
||||
<input type="text" id="inviteLink" readonly>
|
||||
<button id="copyInvite" class="secondary">📋</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 20px;">
|
||||
<label>Peers in Room</label>
|
||||
<div id="peerList" class="info-card">
|
||||
<div style="text-align:center; color: var(--text-muted); font-size: 12px;">No peers connected</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="forceSyncBtn" class="primary" style="background: linear-gradient(135deg, #6366f1, #a855f7); margin-bottom: 12px;">
|
||||
⚡ Force Sync Everyone
|
||||
</button>
|
||||
|
||||
<button id="leaveBtn" class="secondary" style="color: var(--error); border-color: var(--error);">Leave Room</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
+44
-8
@@ -36,7 +36,9 @@ const elements = {
|
||||
publicRooms: document.getElementById('publicRooms'),
|
||||
refreshRooms: document.getElementById('refreshRooms'),
|
||||
roomError: document.getElementById('roomError'),
|
||||
retryBtn: document.getElementById('retryBtn')
|
||||
retryBtn: document.getElementById('retryBtn'),
|
||||
sectionJoin: document.getElementById('section-join'),
|
||||
sectionActive: document.getElementById('section-active')
|
||||
};
|
||||
|
||||
let localPeerId = null;
|
||||
@@ -60,7 +62,8 @@ async function init() {
|
||||
// Populate Tabs
|
||||
await populateTabs();
|
||||
|
||||
updateUI(data.roomId, data.password);
|
||||
toggleUIState(!!data.roomId);
|
||||
updateUI(data.roomId, data.password, data.useCustomServer, data.serverUrl);
|
||||
refreshLogs();
|
||||
refreshHistory();
|
||||
|
||||
@@ -81,11 +84,18 @@ async function init() {
|
||||
}
|
||||
|
||||
// --- UI Logic ---
|
||||
function updateUI(roomId, password) {
|
||||
function toggleUIState(inRoom) {
|
||||
if (elements.sectionJoin) elements.sectionJoin.style.display = inRoom ? 'none' : 'block';
|
||||
if (elements.sectionActive) elements.sectionActive.style.display = inRoom ? 'block' : 'none';
|
||||
}
|
||||
|
||||
function updateUI(roomId, password, useCustomServer = false, serverUrl = '') {
|
||||
const inRoom = !!roomId;
|
||||
elements.roomInfo.style.display = inRoom ? 'block' : 'none';
|
||||
toggleUIState(inRoom);
|
||||
if (inRoom) {
|
||||
const invite = `${OFFICIAL_LANDING_PAGE_URL}/join.html#join:${roomId}:${password}`;
|
||||
const serverFlag = useCustomServer ? '1' : '0';
|
||||
const encodedUrl = encodeURIComponent(serverUrl || '');
|
||||
const invite = `${OFFICIAL_LANDING_PAGE_URL}/join.html#join:${roomId}:${password}:${serverFlag}:${encodedUrl}`;
|
||||
elements.inviteLink.value = invite;
|
||||
}
|
||||
}
|
||||
@@ -250,8 +260,26 @@ function checkInviteLink() {
|
||||
if (tab && tab.url && tab.url.includes(OFFICIAL_LANDING_PAGE_URL) && tab.url.includes('#join:')) {
|
||||
const parts = tab.url.split('#join:')[1].split(':');
|
||||
if (parts.length >= 2) {
|
||||
elements.roomId.value = parts[0];
|
||||
elements.password.value = parts[1];
|
||||
const roomId = parts[0];
|
||||
const password = parts[1];
|
||||
let useCustomServer = false;
|
||||
let serverUrl = '';
|
||||
|
||||
// Smart Link: Parse Server Config if present
|
||||
if (parts.length >= 4) {
|
||||
useCustomServer = parts[2] === '1';
|
||||
serverUrl = decodeURIComponent(parts[3]);
|
||||
}
|
||||
|
||||
elements.roomId.value = roomId;
|
||||
elements.password.value = password;
|
||||
|
||||
if (parts.length >= 4) {
|
||||
elements.serverUrl.value = serverUrl;
|
||||
setServerMode(useCustomServer);
|
||||
chrome.storage.sync.set({ serverUrl, useCustomServer });
|
||||
}
|
||||
|
||||
// Visual feedback
|
||||
elements.joinBtn.style.boxShadow = '0 0 15px var(--accent)';
|
||||
setTimeout(() => elements.joinBtn.style.boxShadow = '', 2000);
|
||||
@@ -332,7 +360,10 @@ elements.joinBtn.addEventListener('click', async () => {
|
||||
|
||||
// Tell background to connect
|
||||
chrome.runtime.sendMessage({ type: 'CONNECT' });
|
||||
updateUI(roomId, password);
|
||||
|
||||
// UI Feedback: Immediately switch state for better responsiveness
|
||||
const data = await chrome.storage.sync.get(['useCustomServer']);
|
||||
updateUI(roomId, password, data.useCustomServer, serverUrl);
|
||||
});
|
||||
|
||||
elements.leaveBtn.addEventListener('click', async () => {
|
||||
@@ -421,6 +452,11 @@ chrome.runtime.onMessage.addListener((msg) => {
|
||||
updateRoomList(msg.rooms);
|
||||
} else if (msg.type === 'LOG_UPDATE' && msg.log && msg.log.type === 'error') {
|
||||
showError(msg.log.message);
|
||||
} else if (msg.type === 'JOIN_STATUS' && msg.success) {
|
||||
// Final confirmation of join from background
|
||||
chrome.storage.sync.get(['roomId', 'password', 'useCustomServer', 'serverUrl'], (data) => {
|
||||
updateUI(data.roomId, data.password, data.useCustomServer, data.serverUrl);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user