fix: resolve pending and jumping

This commit is contained in:
2026-08-03 13:31:45 +02:00
parent 4fcc479779
commit 6f963c7660
9 changed files with 330 additions and 60 deletions

82
tui.go
View File

@@ -577,7 +577,7 @@ func (m App) writeActionUnavailable(action string, thread *ReviewThread) string
}
return ""
}
if m.loading {
if m.loading && m.mutations == nil {
return "write action unavailable while PR data is refreshing"
}
if m.details.FromCache && m.mutations == nil {
@@ -999,7 +999,23 @@ func (m App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
return m, m.difflet.setState(diffletRecoverableError)
}
selected := ""
if msg.operation.Kind == mutationResolution {
selected = m.selectionAfterResolution(
msg.operation.ThreadID, msg.operation.Resolved,
)
}
m.details = m.projectQueuedMutations(m.details)
if msg.operation.Kind == mutationResolution {
if thread := m.threadByID(msg.operation.ThreadID); thread != nil {
m.folded[thread.ID] = thread.IsResolved && m.foldResolved
}
if msg.operation.Resolved {
m.markThreadRead(msg.operation.ThreadID)
}
sortReviewThreads(m.details.Threads, m.threadStatusOrder, m.threadWithinStatus)
m.threadIndex = indexThread(m.details.Threads, selected)
}
m.err = nil
switch msg.operation.Kind {
case mutationReply:
@@ -1017,18 +1033,35 @@ func (m App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
m.writeMode = writeNone
if m.details.FromCache {
return m, m.difflet.setState(diffletIdle)
return m, m.difflet.setState(diffletSuccess)
}
return m, tea.Batch(m.startMutationReplay(), m.difflet.setState(diffletLoading))
return m, tea.Batch(m.startMutationReplay(), m.difflet.setState(diffletSuccess))
case mutationReplayMsg:
m.mutationReplayBusy = false
if msg.state == mutationReplayWaiting {
if msg.err != nil {
m.recordHealth("mutation replay", healthWarning, msg.err.Error())
}
return m, m.difflet.setState(diffletRecoverableError)
m.details = m.projectQueuedMutations(m.details)
m.err = nil
return m, m.difflet.setState(diffletSuccess)
}
if msg.state == mutationReplayVerifying {
m.details = m.projectQueuedMutations(m.details)
m.err = nil
if m.details.Owner == msg.operation.Owner &&
m.details.Repository == msg.operation.Repository &&
m.details.Number == msg.operation.Number {
m.loading = true
return m, tea.Batch(
m.loadDetails(m.details.PullRequest, false),
m.difflet.setState(diffletSuccess),
)
}
return m, m.difflet.setState(diffletSuccess)
}
if msg.state == mutationReplayBlocked {
m.details = m.projectQueuedMutations(m.details)
m.blockedMutation = &msg.operation
m.blockedMutationDetails = msg.details
m.blockedMutationChoice = 0
@@ -1046,8 +1079,18 @@ func (m App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.details.Owner == msg.operation.Owner &&
m.details.Repository == msg.operation.Repository && m.details.Number == msg.operation.Number {
m.loading = true
details := msg.details
requestID := uint64(0)
if m.requests != nil {
requestID = m.requests.supersede()
}
return m, tea.Batch(
m.loadDetails(m.details.PullRequest, false),
func() tea.Msg {
return detailsLoadedMsg{
owner: details.Owner, repo: details.Repository, number: details.Number,
details: details, requestID: requestID,
}
},
m.difflet.setState(diffletSuccess),
)
}
@@ -1091,17 +1134,7 @@ func (m App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.recordHealth("thread resolution", healthError, msg.err.Error())
return m, m.difflet.setState(diffletRecoverableError)
}
selected := ""
if m.threadIndex >= 0 && m.threadIndex < len(m.details.Threads) {
selected = m.details.Threads[m.threadIndex].ID
}
if msg.thread.IsResolved && selected == msg.threadID {
if m.threadIndex+1 < len(m.details.Threads) {
selected = m.details.Threads[m.threadIndex+1].ID
} else if m.threadIndex > 0 {
selected = m.details.Threads[m.threadIndex-1].ID
}
}
selected := m.selectionAfterResolution(msg.threadID, msg.thread.IsResolved)
for index := range m.details.Threads {
if m.details.Threads[index].ID != msg.threadID {
continue
@@ -2460,6 +2493,23 @@ func (m App) threadByID(id string) *ReviewThread {
return nil
}
func (m App) selectionAfterResolution(threadID string, resolved bool) string {
if m.threadIndex < 0 || m.threadIndex >= len(m.details.Threads) {
return ""
}
selected := m.details.Threads[m.threadIndex].ID
if !resolved || selected != threadID {
return selected
}
if m.threadIndex+1 < len(m.details.Threads) {
return m.details.Threads[m.threadIndex+1].ID
}
if m.threadIndex > 0 {
return m.details.Threads[m.threadIndex-1].ID
}
return selected
}
type helpBinding struct {
key string
action string