gui: fix scrolling - use contentHeight not timer

Replace timer-based scroll hack with event-driven approach:
- onContentHeightChanged triggers scroll when content grows
- onMovementEnded detects when user scrolled away from bottom

Scrolling is now driven by actual content changes, not arbitrary delays.
This commit is contained in:
Levi Neely 2026-08-07 18:14:09 +02:00
parent e10912de08
commit cde0284bad
1 changed files with 16 additions and 44 deletions

View File

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