|
|
@@ -3,7 +3,7 @@ package dialog
|
|
|
import (
|
|
|
"github.com/charmbracelet/bubbles/v2/key"
|
|
|
tea "github.com/charmbracelet/bubbletea/v2"
|
|
|
- "github.com/charmbracelet/lipgloss/v2"
|
|
|
+ "github.com/sst/opencode/internal/components/modal"
|
|
|
utilComponents "github.com/sst/opencode/internal/components/util"
|
|
|
"github.com/sst/opencode/internal/layout"
|
|
|
"github.com/sst/opencode/internal/styles"
|
|
|
@@ -19,10 +19,11 @@ type CloseSessionDialogMsg struct {
|
|
|
|
|
|
// SessionDialog interface for the session switching dialog
|
|
|
type SessionDialog interface {
|
|
|
- layout.ModelWithView
|
|
|
+ tea.Model
|
|
|
layout.Bindings
|
|
|
SetSessions(sessions []client.SessionInfo)
|
|
|
SetSelectedSession(sessionID string)
|
|
|
+ Render(background string) string
|
|
|
}
|
|
|
|
|
|
type sessionItem struct {
|
|
|
@@ -48,7 +49,8 @@ func (s sessionItem) Render(selected bool, width int) string {
|
|
|
return baseStyle.Padding(0, 1).Render(s.session.Title)
|
|
|
}
|
|
|
|
|
|
-type sessionDialogComponent struct {
|
|
|
+// sessionDialogContent is the inner content of the session dialog
|
|
|
+type sessionDialogContent struct {
|
|
|
sessions []client.SessionInfo
|
|
|
width int
|
|
|
height int
|
|
|
@@ -72,11 +74,11 @@ var sessionKeys = sessionKeyMap{
|
|
|
),
|
|
|
}
|
|
|
|
|
|
-func (s *sessionDialogComponent) Init() tea.Cmd {
|
|
|
+func (s *sessionDialogContent) Init() tea.Cmd {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-func (s *sessionDialogComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
|
+func (s *sessionDialogContent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
|
switch msg := msg.(type) {
|
|
|
case tea.WindowSizeMsg:
|
|
|
s.width = msg.Width
|
|
|
@@ -110,17 +112,14 @@ func (s *sessionDialogComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
|
return s, cmd
|
|
|
}
|
|
|
|
|
|
-func (s *sessionDialogComponent) View() string {
|
|
|
+func (s *sessionDialogContent) View() string {
|
|
|
t := theme.CurrentTheme()
|
|
|
baseStyle := styles.BaseStyle().Background(t.BackgroundElement())
|
|
|
- outerWidth := layout.Current.Container.Width - 8
|
|
|
- width := outerWidth - 4
|
|
|
+ width := layout.Current.Container.Width - 12
|
|
|
|
|
|
if len(s.sessions) == 0 {
|
|
|
return baseStyle.Padding(1, 2).
|
|
|
- Border(lipgloss.RoundedBorder()).
|
|
|
- BorderBackground(t.Background()).
|
|
|
- BorderForeground(t.TextMuted()).
|
|
|
+ Foreground(t.TextMuted()).
|
|
|
Width(width).
|
|
|
Render("No sessions available")
|
|
|
}
|
|
|
@@ -128,50 +127,46 @@ func (s *sessionDialogComponent) View() string {
|
|
|
// Set the max width for the list
|
|
|
s.list.SetMaxWidth(width)
|
|
|
|
|
|
- title := baseStyle.
|
|
|
- Foreground(t.Primary()).
|
|
|
- Bold(true).
|
|
|
- Width(width).
|
|
|
- Padding(0, 1).
|
|
|
- Render("Switch Session")
|
|
|
-
|
|
|
- content := lipgloss.JoinVertical(
|
|
|
- lipgloss.Left,
|
|
|
- title,
|
|
|
- s.list.View(),
|
|
|
- )
|
|
|
-
|
|
|
- style := styles.BaseStyle().
|
|
|
- PaddingTop(1).
|
|
|
- PaddingBottom(1).
|
|
|
- PaddingLeft(2).
|
|
|
- PaddingRight(2).
|
|
|
- Background(t.BackgroundElement()).
|
|
|
- Foreground(t.TextMuted()).
|
|
|
- BorderStyle(lipgloss.ThickBorder())
|
|
|
-
|
|
|
- style = style.
|
|
|
- BorderLeft(true).
|
|
|
- BorderRight(true).
|
|
|
- BorderLeftForeground(t.BackgroundSubtle()).
|
|
|
- BorderLeftBackground(t.Background()).
|
|
|
- BorderRightForeground(t.BackgroundSubtle()).
|
|
|
- BorderRightBackground(t.Background())
|
|
|
-
|
|
|
- return style.
|
|
|
- Width(outerWidth).
|
|
|
- Render(content)
|
|
|
+ return s.list.View()
|
|
|
}
|
|
|
|
|
|
-func (s *sessionDialogComponent) BindingKeys() []key.Binding {
|
|
|
+func (s *sessionDialogContent) BindingKeys() []key.Binding {
|
|
|
// Combine session dialog keys with list keys
|
|
|
dialogKeys := layout.KeyMapToSlice(sessionKeys)
|
|
|
listKeys := s.list.BindingKeys()
|
|
|
return append(dialogKeys, listKeys...)
|
|
|
}
|
|
|
|
|
|
+// sessionDialogComponent wraps the content with a modal
|
|
|
+type sessionDialogComponent struct {
|
|
|
+ content *sessionDialogContent
|
|
|
+ modal *modal.Modal
|
|
|
+}
|
|
|
+
|
|
|
+func (s *sessionDialogComponent) Init() tea.Cmd {
|
|
|
+ return s.modal.Init()
|
|
|
+}
|
|
|
+
|
|
|
+func (s *sessionDialogComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
|
+ m, cmd := s.modal.Update(msg)
|
|
|
+ s.modal = m.(*modal.Modal)
|
|
|
+ return s, cmd
|
|
|
+}
|
|
|
+
|
|
|
+func (s *sessionDialogComponent) View() string {
|
|
|
+ return s.modal.View()
|
|
|
+}
|
|
|
+
|
|
|
+func (s *sessionDialogComponent) Render(background string) string {
|
|
|
+ return s.modal.Render(background)
|
|
|
+}
|
|
|
+
|
|
|
+func (s *sessionDialogComponent) BindingKeys() []key.Binding {
|
|
|
+ return s.modal.BindingKeys()
|
|
|
+}
|
|
|
+
|
|
|
func (s *sessionDialogComponent) SetSessions(sessions []client.SessionInfo) {
|
|
|
- s.sessions = sessions
|
|
|
+ s.content.sessions = sessions
|
|
|
|
|
|
// Convert sessions to sessionItems
|
|
|
var sessionItems []sessionItem
|
|
|
@@ -180,16 +175,16 @@ func (s *sessionDialogComponent) SetSessions(sessions []client.SessionInfo) {
|
|
|
sessionItems = append(sessionItems, sessionItem{session: sess})
|
|
|
}
|
|
|
|
|
|
- s.list.SetItems(sessionItems)
|
|
|
+ s.content.list.SetItems(sessionItems)
|
|
|
}
|
|
|
|
|
|
func (s *sessionDialogComponent) SetSelectedSession(sessionID string) {
|
|
|
- s.selectedSessionID = sessionID
|
|
|
+ s.content.selectedSessionID = sessionID
|
|
|
|
|
|
// Update the selected index if sessions are already loaded
|
|
|
- if len(s.sessions) > 0 {
|
|
|
+ if len(s.content.sessions) > 0 {
|
|
|
// Re-set the sessions to update the selection
|
|
|
- s.SetSessions(s.sessions)
|
|
|
+ s.SetSessions(s.content.sessions)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -202,9 +197,15 @@ func NewSessionDialogCmp() SessionDialog {
|
|
|
true, // useAlphaNumericKeys
|
|
|
)
|
|
|
|
|
|
- return &sessionDialogComponent{
|
|
|
+ content := &sessionDialogContent{
|
|
|
sessions: []client.SessionInfo{},
|
|
|
selectedSessionID: "",
|
|
|
list: list,
|
|
|
}
|
|
|
+
|
|
|
+ return &sessionDialogComponent{
|
|
|
+ content: content,
|
|
|
+ modal: modal.New(content, modal.WithTitle("Switch Session")),
|
|
|
+ }
|
|
|
}
|
|
|
+
|