discordo/internal/app/app.go
2026-02-23 16:03:11 -05:00

114 lines
2.5 KiB
Go

package app
import (
"fmt"
"log/slog"
"os"
"github.com/ayn2op/discordo/internal/clipboard"
"github.com/ayn2op/discordo/internal/config"
"github.com/ayn2op/discordo/internal/consts"
"github.com/ayn2op/discordo/internal/keyring"
"github.com/ayn2op/discordo/internal/ui/chat"
"github.com/ayn2op/discordo/internal/ui/login"
"github.com/ayn2op/tview"
"github.com/ayn2op/tview/keybind"
"github.com/gdamore/tcell/v3"
)
type App struct {
inner *tview.Application
chatView *chat.View
cfg *config.Config
}
func New(cfg *config.Config) *App {
tview.Styles = tview.Theme{}
app := &App{
inner: tview.NewApplication(),
cfg: cfg,
}
if err := clipboard.Init(); err != nil {
slog.Error("failed to init clipboard", "err", err)
}
app.inner.SetInputCapture(app.onInputCapture)
return app
}
func (a *App) Run() error {
token := os.Getenv("DISCORDO_TOKEN")
if token == "" {
t, err := keyring.GetToken()
if err != nil {
slog.Info("failed to retrieve token from keyring", "err", err)
}
token = t
}
screen, err := tcell.NewScreen()
if err != nil {
return fmt.Errorf("failed to create screen: %w", err)
}
if err := screen.Init(); err != nil {
return fmt.Errorf("failed to init screen: %w", err)
}
if a.cfg.Mouse {
screen.EnableMouse()
}
screen.SetTitle(consts.Name)
screen.EnablePaste()
screen.EnableFocus()
a.inner.SetScreen(screen)
if token == "" {
loginForm := login.NewForm(a.inner, a.cfg, func(token string) {
if err := a.showChatView(token); err != nil {
slog.Error("failed to show chat view", "err", err)
}
})
a.inner.SetRoot(loginForm)
} else {
if err := a.showChatView(token); err != nil {
return err
}
}
return a.inner.Run()
}
func (a *App) showChatView(token string) error {
a.chatView = chat.NewView(a.inner, a.cfg, a.quit)
if err := a.chatView.OpenState(token); err != nil {
return err
}
a.inner.SetRoot(a.chatView)
return nil
}
func (a *App) quit() {
if a.chatView != nil {
if err := a.chatView.CloseState(); err != nil {
slog.Error("failed to close the session", "err", err)
}
}
a.inner.Stop()
}
func (a *App) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
switch {
case keybind.Matches(event, a.cfg.Keybinds.Quit.Keybind):
a.quit()
return nil
case keybind.Matches(event, keybind.NewKeybind(keybind.WithKeys("ctrl+c"))):
// https://github.com/ayn2op/tview/blob/a64fc48d7654432f71922c8b908280cdb525805c/application.go#L153
return tcell.NewEventKey(tcell.KeyCtrlC, "", tcell.ModNone)
}
return event
}