view.go 3.0 KB

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