mirror of
https://github.com/sst/opencode.git
synced 2025-07-07 16:14:59 +00:00
feat(tui): render attachments
This commit is contained in:
parent
f9abc7c84f
commit
94ef341c9d
2 changed files with 51 additions and 3 deletions
|
@ -223,6 +223,7 @@ func renderText(
|
||||||
showToolDetails bool,
|
showToolDetails bool,
|
||||||
highlight bool,
|
highlight bool,
|
||||||
width int,
|
width int,
|
||||||
|
extra string,
|
||||||
toolCalls ...opencode.ToolInvocationPart,
|
toolCalls ...opencode.ToolInvocationPart,
|
||||||
) string {
|
) string {
|
||||||
t := theme.CurrentTheme()
|
t := theme.CurrentTheme()
|
||||||
|
@ -269,7 +270,11 @@ func renderText(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
content = strings.Join([]string{content, info}, "\n")
|
sections := []string{content, info}
|
||||||
|
if extra != "" {
|
||||||
|
sections = append(sections, "\n"+extra)
|
||||||
|
}
|
||||||
|
content = strings.Join(sections, "\n")
|
||||||
|
|
||||||
switch message.Role {
|
switch message.Role {
|
||||||
case opencode.MessageRoleUser:
|
case opencode.MessageRoleUser:
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/sst/opencode-sdk-go"
|
"github.com/sst/opencode-sdk-go"
|
||||||
"github.com/sst/opencode/internal/app"
|
"github.com/sst/opencode/internal/app"
|
||||||
"github.com/sst/opencode/internal/components/dialog"
|
"github.com/sst/opencode/internal/components/dialog"
|
||||||
|
"github.com/sst/opencode/internal/layout"
|
||||||
"github.com/sst/opencode/internal/styles"
|
"github.com/sst/opencode/internal/styles"
|
||||||
"github.com/sst/opencode/internal/theme"
|
"github.com/sst/opencode/internal/theme"
|
||||||
"github.com/sst/opencode/internal/util"
|
"github.com/sst/opencode/internal/util"
|
||||||
|
@ -133,10 +134,49 @@ func (m *messagesComponent) renderView(width int) {
|
||||||
|
|
||||||
switch message.Role {
|
switch message.Role {
|
||||||
case opencode.MessageRoleUser:
|
case opencode.MessageRoleUser:
|
||||||
for _, part := range message.Parts {
|
for partIndex, part := range message.Parts {
|
||||||
switch part := part.AsUnion().(type) {
|
switch part := part.AsUnion().(type) {
|
||||||
case opencode.TextPart:
|
case opencode.TextPart:
|
||||||
key := m.cache.GenerateKey(message.ID, part.Text, width, m.selectedPart == m.partCount)
|
remainingParts := message.Parts[partIndex+1:]
|
||||||
|
fileParts := make([]opencode.FilePart, 0)
|
||||||
|
for _, part := range remainingParts {
|
||||||
|
switch part := part.AsUnion().(type) {
|
||||||
|
case opencode.FilePart:
|
||||||
|
fileParts = append(fileParts, part)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flexItems := []layout.FlexItem{}
|
||||||
|
if len(fileParts) > 0 {
|
||||||
|
fileStyle := styles.NewStyle().Background(t.BackgroundElement()).Foreground(t.TextMuted()).Padding(0, 1)
|
||||||
|
mediaTypeStyle := styles.NewStyle().Background(t.Secondary()).Foreground(t.BackgroundPanel()).Padding(0, 1)
|
||||||
|
for _, filePart := range fileParts {
|
||||||
|
mediaType := ""
|
||||||
|
switch filePart.MediaType {
|
||||||
|
case "text/plain":
|
||||||
|
mediaType = "txt"
|
||||||
|
case "image/png", "image/jpeg", "image/gif", "image/webp":
|
||||||
|
mediaType = "img"
|
||||||
|
case "application/pdf":
|
||||||
|
mediaType = "pdf"
|
||||||
|
}
|
||||||
|
|
||||||
|
flexItems = append(flexItems, layout.FlexItem{
|
||||||
|
View: mediaTypeStyle.Render(mediaType) + fileStyle.Render(filePart.Filename),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bgColor := t.BackgroundPanel()
|
||||||
|
files := layout.Render(
|
||||||
|
layout.FlexOptions{
|
||||||
|
Background: &bgColor,
|
||||||
|
Width: width - 6,
|
||||||
|
Direction: layout.Row,
|
||||||
|
Gap: 3,
|
||||||
|
},
|
||||||
|
flexItems...,
|
||||||
|
)
|
||||||
|
|
||||||
|
key := m.cache.GenerateKey(message.ID, part.Text, width, m.selectedPart == m.partCount, files)
|
||||||
content, cached = m.cache.Get(key)
|
content, cached = m.cache.Get(key)
|
||||||
if !cached {
|
if !cached {
|
||||||
content = renderText(
|
content = renderText(
|
||||||
|
@ -147,6 +187,7 @@ func (m *messagesComponent) renderView(width int) {
|
||||||
m.showToolDetails,
|
m.showToolDetails,
|
||||||
m.partCount == m.selectedPart,
|
m.partCount == m.selectedPart,
|
||||||
width,
|
width,
|
||||||
|
files,
|
||||||
)
|
)
|
||||||
m.cache.Set(key, content)
|
m.cache.Set(key, content)
|
||||||
}
|
}
|
||||||
|
@ -206,6 +247,7 @@ func (m *messagesComponent) renderView(width int) {
|
||||||
m.showToolDetails,
|
m.showToolDetails,
|
||||||
m.partCount == m.selectedPart,
|
m.partCount == m.selectedPart,
|
||||||
width,
|
width,
|
||||||
|
"",
|
||||||
toolCallParts...,
|
toolCallParts...,
|
||||||
)
|
)
|
||||||
m.cache.Set(key, content)
|
m.cache.Set(key, content)
|
||||||
|
@ -219,6 +261,7 @@ func (m *messagesComponent) renderView(width int) {
|
||||||
m.showToolDetails,
|
m.showToolDetails,
|
||||||
m.partCount == m.selectedPart,
|
m.partCount == m.selectedPart,
|
||||||
width,
|
width,
|
||||||
|
"",
|
||||||
toolCallParts...,
|
toolCallParts...,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue