Skip to content

Commit baecede

Browse files
committed
v1.2.2: Hotfix - Console polling fallback + wsproto fix - Added polling fallback to Console tab when WebSocket is disconnected - Fixed wsproto missing from PyInstaller build (caused WebSocket 404 in .exe) - Added wsproto to requirements.txt and GitHub Actions build
1 parent 68159da commit baecede

5 files changed

Lines changed: 66 additions & 2 deletions

File tree

.github/workflows/release.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ jobs:
5252
pyinstaller --onefile --noconsole \
5353
--collect-all uvicorn \
5454
--collect-all fastapi \
55+
--collect-all wsproto \
5556
--hidden-import=uvicorn.logging \
5657
--hidden-import=uvicorn.loops \
5758
--hidden-import=uvicorn.loops.auto \
@@ -134,6 +135,7 @@ jobs:
134135
pyinstaller --onefile --noconsole \
135136
--collect-all uvicorn \
136137
--collect-all fastapi \
138+
--collect-all wsproto \
137139
--hidden-import=uvicorn.logging \
138140
--hidden-import=uvicorn.loops \
139141
--hidden-import=uvicorn.loops.auto \

backend/requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ fastapi>=0.100.0
77
uvicorn>=0.22.0
88
python-multipart>=0.0.6
99
pydantic>=2.0.0
10-
mcstatus>=11.0.0
10+
mcstatus>=11.0.0
11+
wsproto>=1.2.0

changelog.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# Minecraft Server GUI - Changelog
22

3+
## Version 1.2.2 - 2026-05-27 CONSOLE HOTFIX
4+
5+
### CRITICAL FIX:
6+
- **Fixed WebSocket 404 in built .exe** — `wsproto` dependency was missing from PyInstaller build, causing `/ws/console` to return 404 and Console tab to receive no logs
7+
8+
### IMPROVEMENTS:
9+
- **Console polling fallback** — Console tab now fetches logs via REST API when WebSocket is disconnected, matching Dashboard behavior
10+
- Added `wsproto` to `requirements.txt` and GitHub Actions PyInstaller builds
11+
12+
---
13+
314
## Version 1.2.1 - 2026-05-27 CONSOLE & STABILITY UPDATE
415

516
### NEW FEATURES:

electron-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "minecraft-server-gui",
33
"private": true,
4-
"version": "1.2.1",
4+
"version": "1.2.2",
55
"repository": {
66
"type": "git",
77
"url": "https://github.com/CalaKuad1/Minecraft-Local-Server-GUI.git"

electron-app/src/components/Console.jsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,56 @@ export default function Console() {
4444
return subscribe('console', handleMsg);
4545
}, [subscribe]);
4646

47+
// Polling fallback when WebSocket is disconnected
48+
useEffect(() => {
49+
if (isConnected) return;
50+
let cancelled = false;
51+
let timer = null;
52+
53+
const poll = async () => {
54+
if (cancelled) return;
55+
try {
56+
const status = await api.getStatus();
57+
if (cancelled) return;
58+
if (status?.recent_logs && Array.isArray(status.recent_logs)) {
59+
setLogs(prev => {
60+
if (prev.length === 0) {
61+
const items = status.recent_logs.slice(-150).map(item => ({
62+
...item,
63+
_id: ++logIdRef.current,
64+
message: typeof item.message === 'string' ? item.message : String(item.message || ''),
65+
time: item.time || new Date().toLocaleTimeString([], { hour12: false })
66+
}));
67+
return items.slice(-MAX_LOGS);
68+
}
69+
const lastLocal = prev[prev.length - 1];
70+
const newItems = [];
71+
for (const item of status.recent_logs) {
72+
const msg = typeof item.message === 'string' ? item.message : String(item.message || '');
73+
if (lastLocal && msg === lastLocal.message) break;
74+
newItems.unshift({
75+
...item,
76+
_id: ++logIdRef.current,
77+
message: msg,
78+
time: item.time || new Date().toLocaleTimeString([], { hour12: false })
79+
});
80+
}
81+
if (newItems.length === 0) return prev;
82+
const next = [...prev, ...newItems.reverse()];
83+
return next.length > MAX_LOGS ? next.slice(-MAX_LOGS) : next;
84+
});
85+
}
86+
} catch (e) {}
87+
if (!cancelled) timer = setTimeout(poll, 3000);
88+
};
89+
90+
poll();
91+
return () => {
92+
cancelled = true;
93+
if (timer) clearTimeout(timer);
94+
};
95+
}, [isConnected]);
96+
4797
useEffect(() => {
4898
if (scrollRef.current && !userScrolledUpRef.current) {
4999
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;

0 commit comments

Comments
 (0)