Files
FunConnect/client/renderer/app.js

279 lines
8.7 KiB
JavaScript
Raw Normal View History

// FunConnect Client - Renderer Logic
const $ = (sel) => document.querySelector(sel);
const $$ = (sel) => document.querySelectorAll(sel);
let isConnected = false;
let currentServerUrl = '';
// ===== Window Controls =====
$('#btn-min').addEventListener('click', () => window.funmc.minimize());
$('#btn-max').addEventListener('click', () => window.funmc.maximize());
$('#btn-close').addEventListener('click', () => window.funmc.close());
// ===== Navigation =====
$$('.nav-item').forEach(item => {
item.addEventListener('click', () => {
const page = item.dataset.page;
$$('.nav-item').forEach(n => n.classList.remove('active'));
item.classList.add('active');
$$('.page').forEach(p => p.classList.remove('active'));
$(`#page-${page}`).classList.add('active');
});
});
// ===== Connect Page =====
$('#btn-connect').addEventListener('click', async () => {
const url = $('#server-url').value.trim();
if (!url) {
showMsg('#connect-msg', '请输入服务器地址', 'error');
return;
}
const btn = $('#btn-connect');
btn.disabled = true;
btn.innerHTML = '<span class="spinner"></span> 连接中...';
showMsg('#connect-msg', '', '');
const result = await window.funmc.connectServer(url);
if (result.success) {
isConnected = true;
currentServerUrl = url;
updateServerStatus(true);
showMsg('#connect-msg', '连接成功!', 'success');
showServerInfo(result.data);
} else {
isConnected = false;
updateServerStatus(false);
showMsg('#connect-msg', '连接失败: ' + result.error, 'error');
}
btn.disabled = false;
btn.textContent = '连接服务器';
});
function showServerInfo(data) {
const grid = $('#server-info-grid');
grid.innerHTML = '';
const items = [
{ label: '节点名称', value: data.nodeName || 'N/A' },
{ label: '节点ID', value: data.nodeId || 'N/A' },
{ label: '运行模式', value: data.isMaster ? '主节点' : '工作节点' },
{ label: '运行状态', value: data.status === 'ok' ? '正常' : '异常' },
{ label: '运行时间', value: formatUptime(data.uptime || 0) },
{ label: '版本', value: 'v1.0.0' },
];
items.forEach(item => {
const div = document.createElement('div');
div.className = 'info-item';
div.innerHTML = `<div class="label">${item.label}</div><div class="value">${item.value}</div>`;
grid.appendChild(div);
});
$('#server-info').classList.remove('hidden');
}
function updateServerStatus(online) {
const dot = $('#server-status .status-dot');
const text = $('#server-status .status-text');
if (online) {
dot.className = 'status-dot online';
text.textContent = '已连接';
} else {
dot.className = 'status-dot offline';
text.textContent = '未连接';
}
}
// ===== Rooms Page =====
$('#btn-refresh-rooms').addEventListener('click', loadRooms);
async function loadRooms() {
if (!isConnected) {
$('#rooms-list').innerHTML = '<div class="empty-state"><span class="empty-icon">🔗</span><p>请先连接服务器</p></div>';
return;
}
$('#rooms-list').innerHTML = '<div class="empty-state"><span class="spinner"></span><p>加载中...</p></div>';
const result = await window.funmc.listRooms();
if (!result.success) {
$('#rooms-list').innerHTML = `<div class="empty-state"><span class="empty-icon">❌</span><p>${result.error}</p></div>`;
return;
}
const rooms = result.data.rooms || [];
if (rooms.length === 0) {
$('#rooms-list').innerHTML = '<div class="empty-state"><span class="empty-icon">🎮</span><p>暂无在线房间</p></div>';
return;
}
$('#rooms-list').innerHTML = rooms.map(room => `
<div class="room-card" data-id="${room.id}">
<div class="room-left">
<div class="room-icon">🎮</div>
<div>
<div class="room-name">${escapeHtml(room.name)} ${room.password ? '🔒' : ''}</div>
<div class="room-meta">房间号: ${room.id} | 房主: ${escapeHtml(room.hostName)}</div>
</div>
</div>
<div class="room-right">
<span class="room-players">👥 ${room.currentPlayers}/${room.maxPlayers}</span>
<span class="room-version">${room.gameEdition === 'java' ? 'Java' : '基岩'} ${room.gameVersion}</span>
<button class="room-btn-join" onclick="quickJoin('${room.id}')">加入</button>
</div>
</div>
`).join('');
}
function quickJoin(roomId) {
// Navigate to join page and fill in room ID
$$('.nav-item').forEach(n => n.classList.remove('active'));
document.querySelector('[data-page="join"]').classList.add('active');
$$('.page').forEach(p => p.classList.remove('active'));
$('#page-join').classList.add('active');
$('#join-room-id').value = roomId;
}
// ===== Host Page =====
$('#btn-host').addEventListener('click', async () => {
if (!isConnected) {
showMsg('#host-msg', '请先连接服务器', 'error');
return;
}
const name = $('#host-name').value.trim();
const port = parseInt($('#host-port').value);
const version = $('#host-version').value.trim();
const edition = $('#host-edition').value;
const maxPlayers = parseInt($('#host-maxplayers').value);
const password = $('#host-password').value;
if (!name) {
showMsg('#host-msg', '请输入房间名称', 'error');
return;
}
const btn = $('#btn-host');
btn.disabled = true;
btn.innerHTML = '<span class="spinner"></span> 创建中...';
showMsg('#host-msg', '', '');
const result = await window.funmc.hostRoom({
serverUrl: currentServerUrl,
roomName: name,
localMcPort: port,
gameVersion: version,
gameEdition: edition,
maxPlayers: maxPlayers,
password: password || undefined,
});
if (result.success) {
showMsg('#host-msg', '', '');
$('#host-room-id').textContent = result.data.room.id;
$('#host-result').classList.remove('hidden');
} else {
showMsg('#host-msg', '创建失败: ' + result.error, 'error');
}
btn.disabled = false;
btn.textContent = '创建房间';
});
$('#btn-copy-room').addEventListener('click', () => {
const roomId = $('#host-room-id').textContent;
navigator.clipboard.writeText(roomId).then(() => {
$('#btn-copy-room').textContent = '已复制!';
setTimeout(() => { $('#btn-copy-room').textContent = '复制房间号'; }, 2000);
});
});
// ===== Join Page =====
$('#btn-join').addEventListener('click', async () => {
const roomId = $('#join-room-id').value.trim();
const host = $('#join-host').value.trim();
const port = parseInt($('#join-port').value);
const localPort = parseInt($('#join-local-port').value);
if (!roomId) {
showMsg('#join-msg', '请输入房间号', 'error');
return;
}
if (!host) {
showMsg('#join-msg', '请输入中继服务器地址', 'error');
return;
}
const btn = $('#btn-join');
btn.disabled = true;
btn.innerHTML = '<span class="spinner"></span> 连接中...';
showMsg('#join-msg', '', '');
const result = await window.funmc.joinRoom({
serverHost: host,
serverPort: port,
roomId: roomId,
localPort: localPort,
});
if (result.success) {
showMsg('#join-msg', '', '');
$('#join-active-port').textContent = String(localPort);
$('#join-status').classList.remove('hidden');
$('#btn-join').classList.add('hidden');
$('#btn-leave').classList.remove('hidden');
} else {
showMsg('#join-msg', '加入失败: ' + result.error, 'error');
}
btn.disabled = false;
btn.textContent = '加入房间';
});
$('#btn-leave').addEventListener('click', async () => {
await window.funmc.disconnect();
$('#join-status').classList.add('hidden');
$('#btn-join').classList.remove('hidden');
$('#btn-leave').classList.add('hidden');
showMsg('#join-msg', '已断开连接', 'success');
});
// ===== Relay Status Events =====
window.funmc.onRelayStatus((data) => {
if (data.status === 'disconnected') {
$('#join-status').classList.add('hidden');
$('#btn-join').classList.remove('hidden');
$('#btn-leave').classList.add('hidden');
showMsg('#join-msg', '连接已断开', 'error');
} else if (data.status === 'error') {
showMsg('#join-msg', '连接错误: ' + data.error, 'error');
}
});
// ===== Auto-refresh rooms when navigating =====
document.querySelector('[data-page="rooms"]').addEventListener('click', () => {
if (isConnected) loadRooms();
});
// ===== Utilities =====
function showMsg(selector, text, type) {
const el = $(selector);
el.textContent = text;
el.className = 'msg' + (type ? ' ' + type : '');
}
function escapeHtml(str) {
const div = document.createElement('div');
div.textContent = str;
return div.innerHTML;
}
function formatUptime(seconds) {
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = Math.floor(seconds % 60);
if (h > 0) return `${h}${m}${s}`;
if (m > 0) return `${m}${s}`;
return `${s}`;
}