session.go 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. package dialog
  2. import (
  3. "context"
  4. tea "github.com/charmbracelet/bubbletea/v2"
  5. "github.com/sst/opencode/internal/app"
  6. "github.com/sst/opencode/internal/components/list"
  7. "github.com/sst/opencode/internal/components/modal"
  8. "github.com/sst/opencode/internal/layout"
  9. "github.com/sst/opencode/internal/util"
  10. "github.com/sst/opencode/pkg/client"
  11. )
  12. // SessionDialog interface for the session switching dialog
  13. type SessionDialog interface {
  14. layout.Modal
  15. }
  16. type sessionDialog struct {
  17. width int
  18. height int
  19. modal *modal.Modal
  20. sessions []client.SessionInfo
  21. list list.List[list.StringItem]
  22. }
  23. func (s *sessionDialog) Init() tea.Cmd {
  24. return nil
  25. }
  26. func (s *sessionDialog) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
  27. switch msg := msg.(type) {
  28. case tea.WindowSizeMsg:
  29. s.width = msg.Width
  30. s.height = msg.Height
  31. s.list.SetMaxWidth(layout.Current.Container.Width - 12)
  32. case tea.KeyPressMsg:
  33. switch msg.String() {
  34. case "enter":
  35. if _, idx := s.list.GetSelectedItem(); idx >= 0 && idx < len(s.sessions) {
  36. selectedSession := s.sessions[idx]
  37. return s, tea.Sequence(
  38. util.CmdHandler(modal.CloseModalMsg{}),
  39. util.CmdHandler(app.SessionSelectedMsg(&selectedSession)),
  40. )
  41. }
  42. }
  43. }
  44. var cmd tea.Cmd
  45. listModel, cmd := s.list.Update(msg)
  46. s.list = listModel.(list.List[list.StringItem])
  47. return s, cmd
  48. }
  49. func (s *sessionDialog) Render(background string) string {
  50. return s.modal.Render(s.list.View(), background)
  51. }
  52. func (s *sessionDialog) Close() tea.Cmd {
  53. return nil
  54. }
  55. // NewSessionDialog creates a new session switching dialog
  56. func NewSessionDialog(app *app.App) SessionDialog {
  57. sessions, _ := app.ListSessions(context.Background())
  58. var filteredSessions []client.SessionInfo
  59. var sessionTitles []string
  60. for _, sess := range sessions {
  61. if sess.ParentID != nil {
  62. continue
  63. }
  64. filteredSessions = append(filteredSessions, sess)
  65. sessionTitles = append(sessionTitles, sess.Title)
  66. }
  67. list := list.NewStringList(
  68. sessionTitles,
  69. 10, // maxVisibleSessions
  70. "No sessions available",
  71. true, // useAlphaNumericKeys
  72. )
  73. list.SetMaxWidth(layout.Current.Container.Width - 12)
  74. return &sessionDialog{
  75. sessions: filteredSessions,
  76. list: list,
  77. modal: modal.New(
  78. modal.WithTitle("Switch Session"),
  79. modal.WithMaxWidth(layout.Current.Container.Width-8),
  80. ),
  81. }
  82. }