view.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package root
  2. import (
  3. "log/slog"
  4. "github.com/ayn2op/discordo/internal/config"
  5. "github.com/ayn2op/discordo/internal/consts"
  6. "github.com/ayn2op/discordo/internal/ui/chat"
  7. "github.com/ayn2op/discordo/internal/ui/login"
  8. "github.com/ayn2op/tview"
  9. "github.com/ayn2op/tview/keybind"
  10. "github.com/gdamore/tcell/v3"
  11. )
  12. const tokenEnvVarKey = "DISCORDO_TOKEN"
  13. type View struct {
  14. app *tview.Application
  15. inner tview.Primitive
  16. chat *chat.View
  17. cfg *config.Config
  18. }
  19. func NewView(cfg *config.Config, app *tview.Application) *View {
  20. return &View{
  21. app: app,
  22. cfg: cfg,
  23. }
  24. }
  25. func (v *View) showLoginView() {
  26. loginForm := login.NewForm(v.app, v.cfg, func(token string) {
  27. if err := v.showChatView(token); err != nil {
  28. slog.Error("failed to show chat view", "err", err)
  29. }
  30. })
  31. v.chat = nil
  32. v.inner = loginForm
  33. }
  34. func (v *View) showChatView(token string) error {
  35. v.chat = chat.NewView(v.app, v.cfg)
  36. if err := v.chat.OpenState(token); err != nil {
  37. return err
  38. }
  39. v.inner = v.chat
  40. return nil
  41. }
  42. func (v *View) closeChatViewState() {
  43. if v.chat != nil {
  44. if err := v.chat.CloseState(); err != nil {
  45. slog.Error("failed to close the session", "err", err)
  46. }
  47. v.chat = nil
  48. }
  49. }
  50. var _ tview.Primitive = (*View)(nil)
  51. func (v *View) Draw(screen tcell.Screen) {
  52. if v.inner != nil {
  53. v.inner.Draw(screen)
  54. }
  55. }
  56. func (v *View) HandleEvent(event tcell.Event) tview.Command {
  57. switch event := event.(type) {
  58. case *tview.InitEvent:
  59. return tview.BatchCommand{
  60. tview.SetTitleCommand(consts.Name),
  61. tview.EventCommand(initClipboard),
  62. tview.EventCommand(getToken),
  63. }
  64. case *tokenEvent:
  65. if event.token == "" {
  66. v.showLoginView()
  67. } else {
  68. if err := v.showChatView(event.token); err != nil {
  69. slog.Error("failed to show chat view", "err", err)
  70. return tview.QuitCommand{}
  71. }
  72. }
  73. return tview.BatchCommand{tview.SetFocusCommand{Target: v.inner}}
  74. case *chat.LogoutEvent:
  75. v.showLoginView()
  76. return tview.BatchCommand{
  77. tview.EventCommand(deleteToken),
  78. tview.SetFocusCommand{Target: v.inner},
  79. }
  80. case *tview.KeyEvent:
  81. switch {
  82. case keybind.Matches(event, v.cfg.Keybinds.Suspend.Keybind):
  83. v.suspend()
  84. return nil
  85. case keybind.Matches(event, v.cfg.Keybinds.Quit.Keybind):
  86. v.closeChatViewState()
  87. return tview.QuitCommand{}
  88. }
  89. }
  90. if v.inner != nil {
  91. return v.inner.HandleEvent(event)
  92. }
  93. return nil
  94. }
  95. func (v *View) GetRect() (int, int, int, int) {
  96. if v.inner != nil {
  97. return v.inner.GetRect()
  98. }
  99. return 0, 0, 0, 0
  100. }
  101. func (v *View) SetRect(x int, y int, width int, height int) {
  102. if v.inner != nil {
  103. v.inner.SetRect(x, y, width, height)
  104. }
  105. }
  106. func (v *View) Focus(delegate func(p tview.Primitive)) {
  107. if v.inner != nil {
  108. delegate(v.inner)
  109. }
  110. }
  111. func (v *View) HasFocus() bool {
  112. if v.inner != nil {
  113. return v.inner.HasFocus()
  114. }
  115. return true
  116. }
  117. func (v *View) Blur() {
  118. if v.inner != nil {
  119. v.inner.Blur()
  120. }
  121. }