diff --git a/gui/main.qml b/gui/main.qml index 3de2677..2a83f01 100644 --- a/gui/main.qml +++ b/gui/main.qml @@ -93,17 +93,6 @@ ApplicationWindow { // Sidebar visibility property bool sidebarVisible: true - // Deferred scroll timer — fires once after model changes settle - Timer { - id: scrollTimer - interval: 16 // ~1 frame at 60fps, allows layout to settle - repeat: false - onTriggered: { - if (chatView.shouldAutoScroll) - chatView.positionViewAtEnd() - } - } - // Session ID to kill — set on right-click, consumed by context menu property string killTargetSessionId: "" // Target session for "New Agent" dialog @@ -478,7 +467,6 @@ ApplicationWindow { chatModel.trimFront(20) } } - scrollTimer.start() // Ensure we have the latest session list ollie.refreshSessions() buildSessionTree() @@ -496,7 +484,6 @@ ApplicationWindow { chatModel.trimFront(20) } } - scrollTimer.start() } function onActiveAgentIdChanged() { chatModel.reset() @@ -508,7 +495,6 @@ ApplicationWindow { chatModel.trimFront(20) } } - scrollTimer.start() } } @@ -897,40 +883,26 @@ ApplicationWindow { boundsBehavior: Flickable.StopAtBounds visible: ollie.daemonConnected && ollie.activeAgentId !== "" - // Auto-scroll when near bottom (within ~50px or at end) - // Reset to true on new blocks, user can scroll up to disable - property bool shouldAutoScroll: true - readonly property bool nearBottom: contentHeight - contentY - height < 50 + // Auto-scroll state: true = follow new content, false = user scrolled up + property bool shouldAutoScroll: true - onContentYChanged: { - // User scrolled up - disable auto-scroll - // User scrolled to bottom - re-enable - if (dragging || flicking) { - shouldAutoScroll = nearBottom || atYEnd - } - } - - onCountChanged: { - // New block added - always scroll if we were following - if (count > 0) { - if (shouldAutoScroll) - scrollTimer.start() - } + onContentHeightChanged: { + // Content grew — scroll to end if we're following + if (shouldAutoScroll && contentHeight > height) { + positionViewAtEnd() } + } - Connections { - target: chatModel - function onDataChanged() { - // Content updated (streaming) - scroll if following - if (chatView.shouldAutoScroll && chatView.count > 0) - scrollTimer.start() - } - } + onMovementEnded: { + // User finished scrolling — update auto-scroll based on position + // atYEnd is true when scrolled to bottom + shouldAutoScroll = atYEnd + } - delegate: ChatBlockDelegate { - width: chatView.width - 8 - parentListView: chatView - } + delegate: ChatBlockDelegate { + width: chatView.width - 8 + parentListView: chatView + } } }