Build log: jump to failure opens at the failed step's start !149

merged merged by cmc on 2026-09-30 03:58 UTC · krz/gitbay-ios:jump-to-failed-step into main

1 file changed, +11 −3

Layout: unified · split

gitbay/Views/Builds/BuildDetailView.swift +11 −3
@@ -243,7 +243,8 @@ struct BuildDetailView: View {
243243 isOpenByDefault(section, in: detail) != toggled.contains(section.n)
244244 }
245245
246 /// To the end of the failed step, where its error is, or of the log.
246 /// To the top of the failed step, so its output reads from the start,
247 /// or to the last line of the log.
247248 private func scroll(to target: Jump, in detail: BuildDetail, proxy: ScrollViewProxy) {
248249 let log = detail.lines
249250 let index = target == .failure ? log.failed : log.sections.indices.last
@@ -251,10 +252,17 @@ struct BuildDetailView: View {
251252 let section = log.sections[index]
252253 query = ""
253254 if !isOpen(section, in: detail) { toggled.formSymmetricDifference([section.n]) }
254 let anchor: AnyHashable = section.lines.last.map { AnyHashable($0.id) } ?? AnyHashable("step-\(section.n)")
255 // An unstepped log has no headers; its top is the first line.
256 let step: AnyHashable = log.stepped || section.lines.isEmpty
257 ? AnyHashable("step-\(section.n)") : AnyHashable(section.lines[0].id)
258 let last: AnyHashable = section.lines.last.map { AnyHashable($0.id) } ?? step
255259 // Let the opened section lay out before scrolling into it.
256260 Task { @MainActor in
257 proxy.scrollTo(anchor, anchor: .bottom)
261 if target == .failure {
262 proxy.scrollTo(step, anchor: .top)
263 } else {
264 proxy.scrollTo(last, anchor: .bottom)
265 }
258266 }
259267 }
260268}