Add ordering for threads
This commit is contained in:
85
tui.go
85
tui.go
@@ -73,6 +73,8 @@ type App struct {
|
||||
pathScroll bool
|
||||
pathScrollInterval time.Duration
|
||||
pathScrollStep int
|
||||
threadStatusOrder []string
|
||||
threadWithinStatus string
|
||||
}
|
||||
|
||||
type AppSettings struct {
|
||||
@@ -80,6 +82,8 @@ type AppSettings struct {
|
||||
ThreadListWidthPercent int
|
||||
PathScroll bool
|
||||
PathScrollInterval time.Duration
|
||||
ThreadStatusOrder []string
|
||||
ThreadWithinStatus string
|
||||
}
|
||||
|
||||
func defaultAppSettings() AppSettings {
|
||||
@@ -87,6 +91,8 @@ func defaultAppSettings() AppSettings {
|
||||
FoldResolved: true,
|
||||
ThreadListWidthPercent: 33,
|
||||
PathScrollInterval: 350 * time.Millisecond,
|
||||
ThreadStatusOrder: []string{"unresolved", "outdated", "resolved"},
|
||||
ThreadWithinStatus: "file",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +113,8 @@ func NewAppWithSettings(
|
||||
folded: make(map[string]bool), loading: true,
|
||||
foldResolved: settings.FoldResolved, threadListWidthPercent: settings.ThreadListWidthPercent,
|
||||
pathScroll: settings.PathScroll, pathScrollInterval: settings.PathScrollInterval,
|
||||
threadStatusOrder: append([]string(nil), settings.ThreadStatusOrder...),
|
||||
threadWithinStatus: settings.ThreadWithinStatus,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,6 +211,7 @@ func (m App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
if m.threadIndex < len(m.details.Threads) {
|
||||
selected = m.details.Threads[m.threadIndex].ID
|
||||
}
|
||||
sortReviewThreads(msg.details.Threads, m.threadStatusOrder, m.threadWithinStatus)
|
||||
m.details = msg.details
|
||||
m.threadIndex = indexThread(m.details.Threads, selected)
|
||||
if selected != "" && (len(m.details.Threads) == 0 || m.details.Threads[m.threadIndex].ID != selected) {
|
||||
@@ -444,6 +453,82 @@ func (m App) matchingThreadIndices() []int {
|
||||
return indices
|
||||
}
|
||||
|
||||
func sortReviewThreads(threads []ReviewThread, statusOrder []string, withinStatus string) {
|
||||
ranks := map[string]int{
|
||||
"unresolved": 0,
|
||||
"outdated": 1,
|
||||
"resolved": 2,
|
||||
}
|
||||
for rank, status := range statusOrder {
|
||||
ranks[status] = rank
|
||||
}
|
||||
if withinStatus == "" {
|
||||
withinStatus = "file"
|
||||
}
|
||||
sort.SliceStable(threads, func(i, j int) bool {
|
||||
left, right := threads[i], threads[j]
|
||||
leftRank, rightRank := ranks[threadStatus(left)], ranks[threadStatus(right)]
|
||||
if leftRank != rightRank {
|
||||
return leftRank < rightRank
|
||||
}
|
||||
if withinStatus == "timestamp" {
|
||||
if less, decided := compareThreadTimestamps(left, right); decided {
|
||||
return less
|
||||
}
|
||||
}
|
||||
leftPath, rightPath := strings.ToLower(left.Path), strings.ToLower(right.Path)
|
||||
if leftPath != rightPath {
|
||||
return leftPath < rightPath
|
||||
}
|
||||
if left.Line != right.Line {
|
||||
return left.Line < right.Line
|
||||
}
|
||||
if withinStatus != "timestamp" {
|
||||
if less, decided := compareThreadTimestamps(left, right); decided {
|
||||
return less
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
func threadStatus(thread ReviewThread) string {
|
||||
if thread.IsResolved {
|
||||
return "resolved"
|
||||
}
|
||||
if thread.IsOutdated {
|
||||
return "outdated"
|
||||
}
|
||||
return "unresolved"
|
||||
}
|
||||
|
||||
func threadOpenedAt(thread ReviewThread) time.Time {
|
||||
var opened time.Time
|
||||
for _, comment := range thread.Comments {
|
||||
if comment.CreatedAt.IsZero() || (!opened.IsZero() && !comment.CreatedAt.Before(opened)) {
|
||||
continue
|
||||
}
|
||||
opened = comment.CreatedAt
|
||||
}
|
||||
return opened
|
||||
}
|
||||
|
||||
func compareThreadTimestamps(left, right ReviewThread) (less, decided bool) {
|
||||
leftTime, rightTime := threadOpenedAt(left), threadOpenedAt(right)
|
||||
switch {
|
||||
case leftTime.IsZero() && rightTime.IsZero():
|
||||
return false, false
|
||||
case leftTime.IsZero():
|
||||
return false, true
|
||||
case rightTime.IsZero():
|
||||
return true, true
|
||||
case !leftTime.Equal(rightTime):
|
||||
return leftTime.Before(rightTime), true
|
||||
default:
|
||||
return false, false
|
||||
}
|
||||
}
|
||||
|
||||
func (m *App) toStart() {
|
||||
if m.screen == prScreen {
|
||||
m.prIndex = 0
|
||||
|
||||
Reference in New Issue
Block a user