mirror of
https://github.com/boolean-maybe/tiki
synced 2026-04-21 13:37:20 +00:00
141 lines
5.1 KiB
Go
141 lines
5.1 KiB
Go
package view
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/gdamore/tcell/v2"
|
|
"github.com/rivo/tview"
|
|
|
|
"github.com/boolean-maybe/tiki/config"
|
|
taskpkg "github.com/boolean-maybe/tiki/task"
|
|
"github.com/boolean-maybe/tiki/util"
|
|
"github.com/boolean-maybe/tiki/util/gradient"
|
|
)
|
|
|
|
// TaskBox provides a reusable task card widget used in board and backlog views.
|
|
|
|
// applyFrameStyle applies selected/unselected styling to a frame
|
|
func applyFrameStyle(frame *tview.Frame, selected bool, colors *config.ColorConfig) {
|
|
if selected {
|
|
frame.SetBorderColor(colors.TaskBoxSelectedBorder.TCell())
|
|
} else {
|
|
frame.SetBorderColor(colors.TaskBoxUnselectedBorder.TCell())
|
|
if !colors.TaskBoxUnselectedBackground.IsDefault() {
|
|
frame.SetBackgroundColor(colors.TaskBoxUnselectedBackground.TCell())
|
|
}
|
|
}
|
|
}
|
|
|
|
// buildCompactTaskContent builds the content string for compact task display
|
|
func buildCompactTaskContent(task *taskpkg.Task, colors *config.ColorConfig, availableWidth int) string {
|
|
emoji := taskpkg.TypeEmoji(task.Type)
|
|
idGradient := gradient.RenderAdaptiveGradientText(task.ID, colors.TaskBoxIDColor, colors.FallbackTaskIDColor)
|
|
truncatedTitle := tview.Escape(util.TruncateText(task.Title, availableWidth))
|
|
priorityEmoji := taskpkg.PriorityLabel(task.Priority)
|
|
pointsVisual := util.GeneratePointsVisual(task.Points, config.GetMaxPoints(), colors.PointsFilledColor, colors.PointsUnfilledColor)
|
|
|
|
titleTag := colors.TaskBoxTitleColor.Tag().String()
|
|
labelTag := colors.TaskBoxLabelColor.Tag().String()
|
|
|
|
return fmt.Sprintf("%s %s\n%s%s[-]\n%spriority[-] %s %spoints[-] %s%s[-]",
|
|
emoji, idGradient,
|
|
titleTag, truncatedTitle,
|
|
labelTag, priorityEmoji,
|
|
labelTag, labelTag, pointsVisual)
|
|
}
|
|
|
|
// buildExpandedTaskContent builds the content string for expanded task display
|
|
func buildExpandedTaskContent(task *taskpkg.Task, colors *config.ColorConfig, availableWidth int) string {
|
|
emoji := taskpkg.TypeEmoji(task.Type)
|
|
idGradient := gradient.RenderAdaptiveGradientText(task.ID, colors.TaskBoxIDColor, colors.FallbackTaskIDColor)
|
|
truncatedTitle := tview.Escape(util.TruncateText(task.Title, availableWidth))
|
|
|
|
// Extract first 3 lines of description
|
|
descLines := strings.Split(task.Description, "\n")
|
|
descLine1 := ""
|
|
descLine2 := ""
|
|
descLine3 := ""
|
|
|
|
if len(descLines) > 0 {
|
|
descLine1 = tview.Escape(util.TruncateText(descLines[0], availableWidth))
|
|
}
|
|
if len(descLines) > 1 {
|
|
descLine2 = tview.Escape(util.TruncateText(descLines[1], availableWidth))
|
|
}
|
|
if len(descLines) > 2 {
|
|
descLine3 = tview.Escape(util.TruncateText(descLines[2], availableWidth))
|
|
}
|
|
|
|
titleTag := colors.TaskBoxTitleColor.Tag().String()
|
|
labelTag := colors.TaskBoxLabelColor.Tag().String()
|
|
descTag := colors.TaskBoxDescriptionColor.Tag().String()
|
|
tagValueTag := colors.TaskBoxTagValueColor.Tag().String()
|
|
|
|
// Build tags string
|
|
tagsStr := ""
|
|
if len(task.Tags) > 0 {
|
|
tagsStr = labelTag + "Tags:[-] " + tagValueTag + tview.Escape(util.TruncateText(strings.Join(task.Tags, ", "), availableWidth-6)) + "[-]"
|
|
}
|
|
|
|
// Build priority/points line
|
|
priorityEmoji := taskpkg.PriorityLabel(task.Priority)
|
|
pointsVisual := util.GeneratePointsVisual(task.Points, config.GetMaxPoints(), colors.PointsFilledColor, colors.PointsUnfilledColor)
|
|
priorityPointsStr := fmt.Sprintf("%spriority[-] %s %spoints[-] %s%s[-]",
|
|
labelTag, priorityEmoji,
|
|
labelTag, labelTag, pointsVisual)
|
|
|
|
return fmt.Sprintf("%s %s\n%s%s[-]\n%s%s[-]\n%s%s[-]\n%s%s[-]\n%s\n%s",
|
|
emoji, idGradient,
|
|
titleTag, truncatedTitle,
|
|
descTag, descLine1,
|
|
descTag, descLine2,
|
|
descTag, descLine3,
|
|
tagsStr, priorityPointsStr)
|
|
}
|
|
|
|
// CreateCompactTaskBox creates a compact styled task box widget (3 lines)
|
|
func CreateCompactTaskBox(task *taskpkg.Task, selected bool, colors *config.ColorConfig) *tview.Frame {
|
|
textView := tview.NewTextView().
|
|
SetDynamicColors(true).
|
|
SetWordWrap(false)
|
|
|
|
textView.SetDrawFunc(func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) {
|
|
availableWidth := width - config.TaskBoxPaddingCompact
|
|
if availableWidth < config.TaskBoxMinWidth {
|
|
availableWidth = config.TaskBoxMinWidth
|
|
}
|
|
content := buildCompactTaskContent(task, colors, availableWidth)
|
|
textView.SetText(content)
|
|
return x, y, width, height
|
|
})
|
|
|
|
frame := tview.NewFrame(textView).SetBorders(0, 0, 0, 0, 0, 0)
|
|
frame.SetBorder(true)
|
|
applyFrameStyle(frame, selected, colors)
|
|
|
|
return frame
|
|
}
|
|
|
|
// CreateExpandedTaskBox creates an expanded styled task box widget (7 lines)
|
|
func CreateExpandedTaskBox(task *taskpkg.Task, selected bool, colors *config.ColorConfig) *tview.Frame {
|
|
textView := tview.NewTextView().
|
|
SetDynamicColors(true).
|
|
SetWordWrap(false)
|
|
|
|
textView.SetDrawFunc(func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) {
|
|
availableWidth := width - config.TaskBoxPaddingExpanded // less overhead for multiline
|
|
if availableWidth < config.TaskBoxMinWidth {
|
|
availableWidth = config.TaskBoxMinWidth
|
|
}
|
|
content := buildExpandedTaskContent(task, colors, availableWidth)
|
|
textView.SetText(content)
|
|
return x, y, width, height
|
|
})
|
|
|
|
frame := tview.NewFrame(textView).SetBorders(0, 0, 0, 0, 0, 0)
|
|
frame.SetBorder(true)
|
|
applyFrameStyle(frame, selected, colors)
|
|
|
|
return frame
|
|
}
|