stay and start at first attention item
This commit is contained in:
@@ -28,6 +28,7 @@ final class ChatModel {
|
||||
private(set) var hasUnmerged = false
|
||||
@ObservationIgnored var stuck = true
|
||||
@ObservationIgnored var prepended = false
|
||||
@ObservationIgnored var released: Int?
|
||||
@ObservationIgnored private var unmergedTimer: Task<Void, Never>?
|
||||
@ObservationIgnored private var offs: [() -> Void] = []
|
||||
@ObservationIgnored private var focusStart = true
|
||||
@@ -335,6 +336,18 @@ final class ChatModel {
|
||||
return groups
|
||||
}
|
||||
|
||||
var held: Int? {
|
||||
let ids = Set(attention().flatMap(\.rows))
|
||||
guard let first = builder.root.rows.first(where: { ids.contains($0.id) })?.id, first != released else {
|
||||
return nil
|
||||
}
|
||||
return first
|
||||
}
|
||||
|
||||
func release() {
|
||||
released = held ?? released
|
||||
}
|
||||
|
||||
func cycle(_ g: AttentionGroup) {
|
||||
let next = (cursors[g.id] ?? -1) + 1
|
||||
let i = next < g.rows.count ? next : 0
|
||||
@@ -770,16 +783,34 @@ private struct TranscriptScroll: View {
|
||||
model.stuck = new.distance < 80
|
||||
return
|
||||
}
|
||||
if model.stuck && new.distance > 1 && (new.content != old.content || new.visible != old.visible) {
|
||||
if !model.stuck || (new.content == old.content && new.visible == old.visible) {
|
||||
return
|
||||
}
|
||||
if let id = model.held {
|
||||
position.scrollTo(id: id, anchor: .top)
|
||||
} else if new.distance > 1 {
|
||||
position.scrollTo(edge: .bottom)
|
||||
}
|
||||
}
|
||||
.onScrollPhaseChange { _, phase in
|
||||
scrolling = phase.isScrolling
|
||||
if phase == .interacting {
|
||||
model.release()
|
||||
}
|
||||
if !scrolling {
|
||||
model.prependOlder()
|
||||
}
|
||||
}
|
||||
.onChange(of: model.held) { _, id in
|
||||
if !model.stuck || scrolling {
|
||||
return
|
||||
}
|
||||
if let id {
|
||||
position.scrollTo(id: id, anchor: .top)
|
||||
} else {
|
||||
position.scrollTo(edge: .bottom)
|
||||
}
|
||||
}
|
||||
.onChange(of: model.older == nil) {
|
||||
if !scrolling {
|
||||
model.prependOlder()
|
||||
@@ -789,6 +820,7 @@ private struct TranscriptScroll: View {
|
||||
guard let new, new > old ?? 0 else {
|
||||
return
|
||||
}
|
||||
model.release()
|
||||
model.stuck = true
|
||||
position.scrollTo(edge: .bottom)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user