Skip to content

Commit e97e105

Browse files
committed
fixed autoscroll
1 parent 5788ee1 commit e97e105

3 files changed

Lines changed: 13 additions & 7 deletions

File tree

interview_coder/AppModel.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,8 @@ final class AppModel: NSObject, ObservableObject {
547547
}
548548
}
549549
}
550+
// After switching sessions, ensure transcript starts at the top
551+
scrollToTop()
550552
}
551553

552554
func beginInteractivity() {
@@ -625,6 +627,7 @@ final class AppModel: NSObject, ObservableObject {
625627
return
626628
}
627629
isGenerating = true
630+
scrollToTop()
628631
updateWindowSizeForState(animated: false)
629632
defer { isGenerating = false; currentStreamTask = nil }
630633
// Clear any prior TTS so Play controls do not resume old audio
@@ -731,6 +734,7 @@ final class AppModel: NSObject, ObservableObject {
731734

732735
private func performImageOnlyInstruction(_ user: String) async {
733736
isGenerating = true
737+
scrollToTop()
734738
updateWindowSizeForState(animated: false)
735739
defer { isGenerating = false }
736740
clearTTSState()
@@ -1590,6 +1594,7 @@ table{border-collapse:collapse;width:100%;} th,td{border:1px solid rgba(127,127,
15901594
if !allTexts.isEmpty { sections.append("Text Snippets (\(allTexts.count)):\n\(tList)") }
15911595
let user = sections.joined(separator: "\n\n") + "\n\nProvide a single consolidated response."
15921596
isGenerating = true
1597+
scrollToTop()
15931598
webSearchSources = []
15941599
updateWindowSizeForState(animated: false)
15951600
defer { isGenerating = false; currentStreamTask = nil }
@@ -1727,6 +1732,7 @@ table{border-collapse:collapse;width:100%;} th,td{border:1px solid rgba(127,127,
17271732
clearTTSState()
17281733
cancelDeltaTimers(); thinkingText = ""; outputDeltaBuffer = ""; thinkingDeltaBuffer = ""; reasoningEncryptedItems.removeAll(); reasoningSummaryBuffer = ""
17291734
isGenerating = true
1735+
scrollToTop()
17301736
updateWindowSizeForState(animated: false)
17311737
defer { isGenerating = false; currentStreamTask = nil }
17321738

interview_coder/PanelView.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ struct PanelView: View {
228228
Label("\(model.selectedProfileName)", systemImage: "person.text.rectangle")
229229
}
230230
.menuStyle(.borderedButton)
231+
// Ensure app stays active when opening the profile menu
232+
.simultaneousGesture(TapGesture().onEnded { NSApp.activate(ignoringOtherApps: true) })
231233
.help("Select system prompt profile")
232234
.frame(width: 120, alignment: .leading)
233235
} else {

interview_coder/ResultScrollView.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,13 @@ struct ResultScrollView<Content: View>: NSViewRepresentable {
6161
let currentBottom = nsView.contentInsets.bottom
6262
let targetBottom = model.showManualInput ? manualInset : baseInset
6363
if currentBottom != targetBottom {
64+
let cv = nsView.contentView
65+
let prevOrigin = cv.bounds.origin
6466
nsView.contentInsets = NSEdgeInsets(top: 0, left: 0, bottom: targetBottom, right: 0)
65-
// Maintain top anchoring when inset changes to avoid visual jump
6667
model.resultsScrollView = nsView
67-
if let doc = nsView.documentView {
68-
let cv = nsView.contentView
69-
let atTopY: CGFloat = doc.isFlipped ? 0 : max(0, doc.bounds.height - cv.bounds.height)
70-
cv.scroll(to: NSPoint(x: 0, y: atTopY))
71-
nsView.reflectScrolledClipView(cv)
72-
}
68+
// Preserve previous scroll position instead of jumping to top
69+
cv.scroll(to: prevOrigin)
70+
nsView.reflectScrolledClipView(cv)
7371
} else {
7472
nsView.contentInsets = NSEdgeInsets(top: 0, left: 0, bottom: targetBottom, right: 0)
7573
model.resultsScrollView = nsView

0 commit comments

Comments
 (0)