mirror of
https://github.com/sst/opencode.git
synced 2025-08-04 13:30:52 +00:00
149 lines
3.6 KiB
Go
149 lines
3.6 KiB
Go
package logs
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/charmbracelet/bubbles/key"
|
|
"github.com/charmbracelet/bubbles/viewport"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/charmbracelet/lipgloss"
|
|
"github.com/kujtimiihoxha/opencode/internal/logging"
|
|
"github.com/kujtimiihoxha/opencode/internal/tui/layout"
|
|
"github.com/kujtimiihoxha/opencode/internal/tui/styles"
|
|
)
|
|
|
|
type DetailComponent interface {
|
|
tea.Model
|
|
layout.Sizeable
|
|
layout.Bindings
|
|
}
|
|
|
|
type detailCmp struct {
|
|
width, height int
|
|
currentLog logging.LogMessage
|
|
viewport viewport.Model
|
|
}
|
|
|
|
func (i *detailCmp) Init() tea.Cmd {
|
|
messages := logging.List()
|
|
if len(messages) == 0 {
|
|
return nil
|
|
}
|
|
i.currentLog = messages[0]
|
|
return nil
|
|
}
|
|
|
|
func (i *detailCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
switch msg := msg.(type) {
|
|
case selectedLogMsg:
|
|
if msg.ID != i.currentLog.ID {
|
|
i.currentLog = logging.LogMessage(msg)
|
|
i.updateContent()
|
|
}
|
|
}
|
|
|
|
return i, nil
|
|
}
|
|
|
|
func (i *detailCmp) updateContent() {
|
|
var content strings.Builder
|
|
|
|
// Format the header with timestamp and level
|
|
timeStyle := lipgloss.NewStyle().Foreground(styles.SubText0)
|
|
levelStyle := getLevelStyle(i.currentLog.Level)
|
|
|
|
header := lipgloss.JoinHorizontal(
|
|
lipgloss.Center,
|
|
timeStyle.Render(i.currentLog.Time.Format(time.RFC3339)),
|
|
" ",
|
|
levelStyle.Render(i.currentLog.Level),
|
|
)
|
|
|
|
content.WriteString(lipgloss.NewStyle().Bold(true).Render(header))
|
|
content.WriteString("\n\n")
|
|
|
|
// Message with styling
|
|
messageStyle := lipgloss.NewStyle().Bold(true).Foreground(styles.Text)
|
|
content.WriteString(messageStyle.Render("Message:"))
|
|
content.WriteString("\n")
|
|
content.WriteString(lipgloss.NewStyle().Padding(0, 2).Render(i.currentLog.Message))
|
|
content.WriteString("\n\n")
|
|
|
|
// Attributes section
|
|
if len(i.currentLog.Attributes) > 0 {
|
|
attrHeaderStyle := lipgloss.NewStyle().Bold(true).Foreground(styles.Text)
|
|
content.WriteString(attrHeaderStyle.Render("Attributes:"))
|
|
content.WriteString("\n")
|
|
|
|
// Create a table-like display for attributes
|
|
keyStyle := lipgloss.NewStyle().Foreground(styles.Primary).Bold(true)
|
|
valueStyle := lipgloss.NewStyle().Foreground(styles.Text)
|
|
|
|
for _, attr := range i.currentLog.Attributes {
|
|
attrLine := fmt.Sprintf("%s: %s",
|
|
keyStyle.Render(attr.Key),
|
|
valueStyle.Render(attr.Value),
|
|
)
|
|
content.WriteString(lipgloss.NewStyle().Padding(0, 2).Render(attrLine))
|
|
content.WriteString("\n")
|
|
}
|
|
}
|
|
|
|
i.viewport.SetContent(content.String())
|
|
}
|
|
|
|
func getLevelStyle(level string) lipgloss.Style {
|
|
style := lipgloss.NewStyle().Bold(true)
|
|
|
|
switch strings.ToLower(level) {
|
|
case "info":
|
|
return style.Foreground(styles.Blue)
|
|
case "warn", "warning":
|
|
return style.Foreground(styles.Warning)
|
|
case "error", "err":
|
|
return style.Foreground(styles.Error)
|
|
case "debug":
|
|
return style.Foreground(styles.Green)
|
|
default:
|
|
return style.Foreground(styles.Text)
|
|
}
|
|
}
|
|
|
|
func (i *detailCmp) View() string {
|
|
return styles.ForceReplaceBackgroundWithLipgloss(i.viewport.View(), styles.Background)
|
|
}
|
|
|
|
func (i *detailCmp) GetSize() (int, int) {
|
|
return i.width, i.height
|
|
}
|
|
|
|
func (i *detailCmp) SetSize(width int, height int) {
|
|
i.width = width
|
|
i.height = height
|
|
i.viewport.Width = i.width
|
|
i.viewport.Height = i.height
|
|
i.updateContent()
|
|
}
|
|
|
|
func (i *detailCmp) BindingKeys() []key.Binding {
|
|
return []key.Binding{
|
|
i.viewport.KeyMap.PageDown,
|
|
i.viewport.KeyMap.PageUp,
|
|
i.viewport.KeyMap.HalfPageDown,
|
|
i.viewport.KeyMap.HalfPageUp,
|
|
}
|
|
}
|
|
|
|
func (i *detailCmp) BorderText() map[layout.BorderPosition]string {
|
|
return map[layout.BorderPosition]string{
|
|
layout.TopLeftBorder: "Log Details",
|
|
}
|
|
}
|
|
|
|
func NewLogsDetails() DetailComponent {
|
|
return &detailCmp{
|
|
viewport: viewport.New(0, 0),
|
|
}
|
|
}
|