refactor(ui): route auth and quit through events

This commit is contained in:
ayn2op 2026-03-04 00:43:34 -05:00
parent 41a6833b81
commit 5afee6e9fa
5 changed files with 57 additions and 51 deletions

View file

@ -9,3 +9,11 @@ func NewLogoutEvent() *LogoutEvent {
event.SetEventNow()
return event
}
type QuitEvent struct{ tcell.EventTime }
func NewQuitEvent() *QuitEvent {
event := &QuitEvent{}
event.SetEventNow()
return event
}

View file

@ -50,9 +50,10 @@ type View struct {
app *tview.Application
cfg *config.Config
state *ningen.State
token string
}
func NewView(app *tview.Application, cfg *config.Config) *View {
func NewView(app *tview.Application, cfg *config.Config, token string) *View {
v := &View{
Layers: layers.New(),
@ -62,8 +63,9 @@ func NewView(app *tview.Application, cfg *config.Config) *View {
typers: make(map[discord.UserID]*time.Timer),
app: app,
cfg: cfg,
app: app,
cfg: cfg,
token: token,
}
v.guildsTree = newGuildsTree(cfg, v)
@ -220,6 +222,19 @@ func (v *View) focusNext() {
func (v *View) HandleEvent(event tcell.Event) tview.Command {
switch event := event.(type) {
case *tview.InitEvent:
return tview.EventCommand(func() tcell.Event {
if err := v.OpenState(v.token); err != nil {
slog.Error("failed to open chat state", "err", err)
return tcell.NewEventError(err)
}
return nil
})
case *QuitEvent:
if err := v.CloseState(); err != nil {
slog.Error("failed to close the session", "err", err)
}
return tview.QuitCommand{}
case *tview.KeyEvent:
redraw := tview.RedrawCommand{}
switch {

View file

@ -0,0 +1,14 @@
package login
import "github.com/gdamore/tcell/v3"
type TokenEvent struct {
tcell.EventTime
Token string
}
func NewTokenEvent(token string) *TokenEvent {
event := &TokenEvent{Token: token}
event.SetEventNow()
return event
}

View file

@ -20,23 +20,19 @@ const (
qrLayerName = "qr"
)
type DoneFn = func(token string)
type Form struct {
*layers.Layers
app *tview.Application
cfg *config.Config
form *tview.Form
done DoneFn
}
func NewForm(app *tview.Application, cfg *config.Config, done DoneFn) *Form {
func NewForm(app *tview.Application, cfg *config.Config) *Form {
f := &Form{
Layers: layers.New(),
app: app,
cfg: cfg,
form: tview.NewForm(),
done: done,
}
f.form.
@ -56,10 +52,7 @@ func (f *Form) login() {
}
go keyring.SetToken(token)
if f.done != nil {
f.done(token)
}
f.app.QueueEvent(NewTokenEvent(token))
}
func (f *Form) onError(err error) {
@ -118,9 +111,7 @@ func (f *Form) loginWithQR() {
go keyring.SetToken(token)
f.RemoveLayer(qrLayerName)
if f.done != nil {
f.done(token)
}
f.app.QueueEvent(NewTokenEvent(token))
})
f.AddLayer(qr, layers.WithName(qrLayerName), layers.WithResize(true), layers.WithVisible(true))

View file

@ -1,8 +1,6 @@
package root
import (
"log/slog"
"github.com/ayn2op/discordo/internal/config"
"github.com/ayn2op/discordo/internal/consts"
"github.com/ayn2op/discordo/internal/ui/chat"
@ -17,9 +15,7 @@ const tokenEnvVarKey = "DISCORDO_TOKEN"
type View struct {
app *tview.Application
inner tview.Primitive
chat *chat.View
cfg *config.Config
cfg *config.Config
}
func NewView(cfg *config.Config, app *tview.Application) *View {
@ -29,32 +25,14 @@ func NewView(cfg *config.Config, app *tview.Application) *View {
}
}
func (v *View) showLoginView() {
loginForm := login.NewForm(v.app, v.cfg, func(token string) {
if err := v.showChatView(token); err != nil {
slog.Error("failed to show chat view", "err", err)
}
})
v.chat = nil
v.inner = loginForm
func (v *View) showLoginView() tview.Command {
v.inner = login.NewForm(v.app, v.cfg)
return v.inner.HandleEvent(tview.NewInitEvent())
}
func (v *View) showChatView(token string) error {
v.chat = chat.NewView(v.app, v.cfg)
if err := v.chat.OpenState(token); err != nil {
return err
}
v.inner = v.chat
return nil
}
func (v *View) closeChatViewState() {
if v.chat != nil {
if err := v.chat.CloseState(); err != nil {
slog.Error("failed to close the session", "err", err)
}
v.chat = nil
}
func (v *View) showChatView(token string) tview.Command {
v.inner = chat.NewView(v.app, v.cfg, token)
return v.inner.HandleEvent(tview.NewInitEvent())
}
var _ tview.Primitive = (*View)(nil)
@ -75,14 +53,12 @@ func (v *View) HandleEvent(event tcell.Event) tview.Command {
}
case *tokenEvent:
if event.token == "" {
v.showLoginView()
return tview.BatchCommand{v.showLoginView(), tview.SetFocusCommand{Target: v.inner}}
} else {
if err := v.showChatView(event.token); err != nil {
slog.Error("failed to show chat view", "err", err)
return tview.QuitCommand{}
}
return tview.BatchCommand{v.showChatView(event.token), tview.SetFocusCommand{Target: v.inner}}
}
return tview.BatchCommand{tview.SetFocusCommand{Target: v.inner}}
case *login.TokenEvent:
return tview.BatchCommand{v.showChatView(event.Token), tview.SetFocusCommand{Target: v.inner}}
case *chat.LogoutEvent:
v.showLoginView()
return tview.BatchCommand{
@ -96,7 +72,9 @@ func (v *View) HandleEvent(event tcell.Event) tview.Command {
v.suspend()
return nil
case keybind.Matches(event, v.cfg.Keybinds.Quit.Keybind):
v.closeChatViewState()
if v.inner != nil {
return v.inner.HandleEvent(chat.NewQuitEvent())
}
return tview.QuitCommand{}
}
}