model.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package login
  2. import (
  3. "log/slog"
  4. "github.com/ayn2op/tview/layers"
  5. "github.com/ayn2op/tview/tabs"
  6. "github.com/gdamore/tcell/v3"
  7. "github.com/ayn2op/discordo/internal/config"
  8. "github.com/ayn2op/discordo/internal/ui"
  9. "github.com/ayn2op/discordo/internal/ui/login/qr"
  10. "github.com/ayn2op/discordo/internal/ui/login/token"
  11. "github.com/ayn2op/tview"
  12. )
  13. const (
  14. tabsLayerName = "tabs"
  15. errorLayerName = "error"
  16. )
  17. type Model struct {
  18. *layers.Layers
  19. tabs *tabs.Model
  20. app *tview.Application
  21. cfg *config.Config
  22. errorModalText string
  23. }
  24. func NewModel(app *tview.Application, cfg *config.Config) *Model {
  25. tabs := tabs.NewModel([]tabs.Tab{token.NewModel(), qr.NewModel(app)})
  26. l := layers.New()
  27. ui.ConfigureBox(l.Box, &cfg.Theme)
  28. l.SetBackgroundLayerStyle(cfg.Theme.Dialog.BackgroundStyle.Style)
  29. l.AddLayer(tabs, layers.WithName(tabsLayerName), layers.WithResize(true), layers.WithVisible(true))
  30. return &Model{
  31. Layers: l,
  32. tabs: tabs,
  33. app: app,
  34. cfg: cfg,
  35. }
  36. }
  37. func (m *Model) HandleEvent(event tcell.Event) tview.Command {
  38. switch event := event.(type) {
  39. case *tcell.EventError:
  40. if m.HasLayer(errorLayerName) {
  41. return tview.RedrawCommand{}
  42. }
  43. m.onError(event)
  44. return tview.RedrawCommand{}
  45. case *tview.ModalDoneEvent:
  46. if !m.HasLayer(errorLayerName) {
  47. return nil
  48. }
  49. if event.ButtonIndex == 0 {
  50. return setClipboard(m.errorModalText)
  51. }
  52. m.RemoveLayer(errorLayerName)
  53. m.errorModalText = ""
  54. return tview.RedrawCommand{}
  55. }
  56. return m.Layers.HandleEvent(event)
  57. }
  58. func (m *Model) onError(err error) {
  59. slog.Error("failed to login", "err", err)
  60. message := err.Error()
  61. m.errorModalText = message
  62. modal := tview.NewModal().
  63. SetText(message).
  64. AddButtons([]string{"Copy", "Close"})
  65. {
  66. bg := m.cfg.Theme.Dialog.Style.GetBackground()
  67. buttonStyle := m.cfg.Theme.Dialog.Style.Style
  68. if bg != tcell.ColorDefault {
  69. modal.SetBackgroundColor(bg)
  70. buttonStyle = buttonStyle.Background(bg)
  71. }
  72. fg := m.cfg.Theme.Dialog.Style.GetForeground()
  73. if fg != tcell.ColorDefault {
  74. modal.SetTextColor(fg)
  75. buttonStyle = buttonStyle.Foreground(fg)
  76. }
  77. // Keep button styles aligned with dialog content and still show focus.
  78. modal.SetButtonStyle(buttonStyle)
  79. modal.SetButtonActivatedStyle(buttonStyle.Reverse(true))
  80. }
  81. m.
  82. AddLayer(
  83. ui.Centered(modal, 0, 0),
  84. layers.WithName(errorLayerName),
  85. layers.WithResize(true),
  86. layers.WithVisible(true),
  87. layers.WithOverlay(),
  88. ).
  89. SendToFront(errorLayerName)
  90. modal.SetFocus(0)
  91. m.app.SetFocus(modal)
  92. }