mirror of
https://github.com/MarekWo/mc-webui.git
synced 2026-05-09 06:44:41 +02:00
fix(console): open at bottom, drop Disconnected from transcript, add jump-to-latest button
- Stop persisting "Disconnected" / "Failed to connect" — these are session-local events; saving them made every reopen begin with a stale red error. - Scroll to the bottom after restoring transcript so reopens land at the latest entry instead of the top. - Add a floating chat-style jump-to-latest button that appears whenever the user scrolls more than ~80px above the bottom and disappears once they're back at the latest entry. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,7 @@ document.addEventListener('DOMContentLoaded', async function() {
|
||||
setupInputHandlers();
|
||||
setupHistoryDropdown();
|
||||
setupClearOutputButton();
|
||||
setupScrollToBottom();
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -58,7 +59,8 @@ function connectWebSocket() {
|
||||
isConnected = false;
|
||||
updateStatus('disconnected');
|
||||
enableInput(false);
|
||||
addMessage('Disconnected', 'error');
|
||||
// Transient session event — show inline but don't persist to transcript
|
||||
addMessage('Disconnected', 'error', false);
|
||||
|
||||
// Clear pending command indicator
|
||||
if (pendingCommandDiv) {
|
||||
@@ -102,7 +104,7 @@ function connectWebSocket() {
|
||||
} catch (error) {
|
||||
console.error('Failed to create WebSocket connection:', error);
|
||||
updateStatus('disconnected');
|
||||
addMessage('Failed to connect: ' + error.message, 'error');
|
||||
addMessage('Failed to connect: ' + error.message, 'error', false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,6 +458,8 @@ async function loadOutputHistory() {
|
||||
const divider = document.createElement('hr');
|
||||
divider.className = 'history-divider';
|
||||
container.appendChild(divider);
|
||||
// Open at the bottom of the transcript, like a chat window
|
||||
scrollToBottom();
|
||||
} catch (error) {
|
||||
console.error('Failed to load output history:', error);
|
||||
}
|
||||
@@ -502,3 +506,28 @@ function setupClearOutputButton() {
|
||||
clearOutputHistory();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wire the floating scroll-to-bottom button: visible when the user has
|
||||
* scrolled away from the bottom of the transcript.
|
||||
*/
|
||||
function setupScrollToBottom() {
|
||||
const container = document.getElementById('consoleMessages');
|
||||
const btn = document.getElementById('scrollBottomBtn');
|
||||
if (!container || !btn) return;
|
||||
|
||||
const SHOW_THRESHOLD = 80; // px from bottom before button appears
|
||||
|
||||
const update = () => {
|
||||
const distance = container.scrollHeight - container.scrollTop - container.clientHeight;
|
||||
btn.classList.toggle('show', distance > SHOW_THRESHOLD);
|
||||
};
|
||||
|
||||
container.addEventListener('scroll', update, { passive: true });
|
||||
// Re-check after content changes (new messages, dropdowns, etc.)
|
||||
new MutationObserver(update).observe(container, { childList: true, subtree: false });
|
||||
btn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
container.scrollTop = container.scrollHeight;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -44,6 +44,13 @@
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.messages-wrap {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.console-messages {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
@@ -52,6 +59,34 @@
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.scroll-bottom-btn {
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
bottom: 1rem;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #0f3460;
|
||||
background-color: #16213e;
|
||||
color: #4ecdc4;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
|
||||
cursor: pointer;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.scroll-bottom-btn.show {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.scroll-bottom-btn:hover {
|
||||
background-color: #1a1a4e;
|
||||
color: #00ff88;
|
||||
}
|
||||
|
||||
.console-message {
|
||||
margin-bottom: 1rem;
|
||||
font-family: 'Courier New', Consolas, monospace;
|
||||
@@ -277,8 +312,13 @@
|
||||
</div>
|
||||
|
||||
<!-- Messages Area -->
|
||||
<div class="console-messages" id="consoleMessages">
|
||||
<div class="console-message system">Type 'help' for available commands.</div>
|
||||
<div class="messages-wrap">
|
||||
<div class="console-messages" id="consoleMessages">
|
||||
<div class="console-message system">Type 'help' for available commands.</div>
|
||||
</div>
|
||||
<button type="button" class="scroll-bottom-btn" id="scrollBottomBtn" title="Scroll to latest" aria-label="Scroll to latest">
|
||||
<i class="bi bi-arrow-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Input Area -->
|
||||
|
||||
Reference in New Issue
Block a user