model.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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. cfg *config.Config
  21. errorModalText string
  22. }
  23. func NewModel(cfg *config.Config) *Model {
  24. tabs := tabs.NewModel([]tabs.Tab{token.NewModel(), qr.NewModel()})
  25. l := layers.New()
  26. ui.ConfigureBox(l.Box, &cfg.Theme)
  27. l.SetBackgroundLayerStyle(cfg.Theme.Dialog.BackgroundStyle.Style)
  28. l.AddLayer(tabs, layers.WithName(tabsLayerName), layers.WithResize(true), layers.WithVisible(true))
  29. return &Model{
  30. Layers: l,
  31. tabs: tabs,
  32. cfg: cfg,
  33. }
  34. }
  35. func (m *Model) HandleEvent(event tcell.Event) tview.Command {
  36. switch event := event.(type) {
  37. case *tcell.EventError:
  38. if m.HasLayer(errorLayerName) {
  39. return nil
  40. }
  41. return m.showErrorDialog(event)
  42. case *tview.ModalDoneEvent:
  43. if !m.HasLayer(errorLayerName) {
  44. return nil
  45. }
  46. if event.ButtonIndex == 0 {
  47. return setClipboard(m.errorModalText)
  48. }
  49. m.RemoveLayer(errorLayerName)
  50. m.errorModalText = ""
  51. return nil
  52. }
  53. return m.Layers.HandleEvent(event)
  54. }
  55. func (m *Model) showErrorDialog(err error) tview.Command {
  56. slog.Error("failed to login", "err", err)
  57. message := err.Error()
  58. m.errorModalText = message
  59. modal := tview.NewModal().
  60. SetText(message).
  61. AddButtons([]string{"Copy", "Close"})
  62. {
  63. bg := m.cfg.Theme.Dialog.Style.GetBackground()
  64. buttonStyle := m.cfg.Theme.Dialog.Style.Style
  65. if bg != tcell.ColorDefault {
  66. modal.SetBackgroundColor(bg)
  67. buttonStyle = buttonStyle.Background(bg)
  68. }
  69. fg := m.cfg.Theme.Dialog.Style.GetForeground()
  70. if fg != tcell.ColorDefault {
  71. modal.SetTextColor(fg)
  72. buttonStyle = buttonStyle.Foreground(fg)
  73. }
  74. // Keep button styles aligned with dialog content and still show focus.
  75. modal.SetButtonStyle(buttonStyle)
  76. modal.SetButtonActivatedStyle(buttonStyle.Reverse(true))
  77. }
  78. m.
  79. AddLayer(
  80. ui.Centered(modal, 0, 0),
  81. layers.WithName(errorLayerName),
  82. layers.WithResize(true),
  83. layers.WithVisible(true),
  84. layers.WithOverlay(),
  85. ).
  86. SendToFront(errorLayerName)
  87. return tview.SetFocus(modal)
  88. }