From 34158b2f9e2220a0e998172a11a4da37c1d9de40 Mon Sep 17 00:00:00 2001 From: ayn2op Date: Fri, 28 Feb 2025 17:29:03 -0500 Subject: [PATCH] refactor: layout -> app --- cmd/{layout.go => app.go} | 92 +++++++++++++++++++-------------------- cmd/guilds_tree.go | 12 ++--- cmd/message_input.go | 10 ++--- cmd/messages_text.go | 34 +++++++-------- cmd/run.go | 6 +-- cmd/state.go | 43 ++++++++---------- 6 files changed, 96 insertions(+), 101 deletions(-) rename cmd/{layout.go => app.go} (52%) diff --git a/cmd/layout.go b/cmd/app.go similarity index 52% rename from cmd/layout.go rename to cmd/app.go index 1a50faf..b03d05b 100644 --- a/cmd/layout.go +++ b/cmd/app.go @@ -11,20 +11,22 @@ import ( "github.com/zalando/go-keyring" ) -type Layout struct { +type App struct { + *tview.Application + cfg *config.Config - app *tview.Application flex *tview.Flex guildsTree *GuildsTree messagesText *MessagesText messageInput *MessageInput } -func newLayout(cfg *config.Config) *Layout { +func newApp(cfg *config.Config) *App { app := tview.NewApplication() - l := &Layout{ + a := &App{ + Application: app, + cfg: cfg, - app: app, flex: tview.NewFlex(), guildsTree: newGuildsTree(app, cfg), @@ -32,66 +34,64 @@ func newLayout(cfg *config.Config) *Layout { messageInput: newMessageInput(app, cfg), } - l.init() - - l.app.EnableMouse(cfg.Mouse) - l.app.SetInputCapture(l.onAppInputCapture) - - l.flex.SetInputCapture(l.onFlexInputCapture) - return l + a.init() + a.EnableMouse(cfg.Mouse) + a.SetInputCapture(a.onInputCapture) + a.flex.SetInputCapture(a.onFlexInputCapture) + return a } -func (l *Layout) show(token string) error { +func (app *App) show(token string) error { if token == "" { - loginForm := login.NewForm(l.app, func(token string) { - if err := l.show(token); err != nil { + loginForm := login.NewForm(app.Application, func(token string) { + if err := app.show(token); err != nil { slog.Error("failed to show app", "err", err) return } }) - l.app.SetRoot(loginForm, true) + app.SetRoot(loginForm, true) } else { - if err := openState(token, l.app, l.cfg); err != nil { + if err := openState(token); err != nil { return err } - l.app.SetRoot(l.flex, true) + app.SetRoot(app.flex, true) } return nil } -func (l *Layout) run(token string) error { - if err := l.show(token); err != nil { +func (app *App) run(token string) error { + if err := app.show(token); err != nil { return err } - return l.app.Run() + return app.Run() } -func (l *Layout) init() { - l.flex.Clear() +func (app *App) init() { + app.flex.Clear() right := tview.NewFlex() right.SetDirection(tview.FlexRow) - right.AddItem(l.messagesText, 0, 1, false) - right.AddItem(l.messageInput, 3, 1, false) + right.AddItem(app.messagesText, 0, 1, false) + right.AddItem(app.messageInput, 3, 1, false) // The guilds tree is always focused first at start-up. - l.flex.AddItem(l.guildsTree, 0, 1, true) - l.flex.AddItem(right, 0, 4, false) + app.flex.AddItem(app.guildsTree, 0, 1, true) + app.flex.AddItem(right, 0, 4, false) } -func (l *Layout) onAppInputCapture(event *tcell.EventKey) *tcell.EventKey { +func (app *App) onInputCapture(event *tcell.EventKey) *tcell.EventKey { switch event.Name() { - case l.cfg.Keys.Quit: + case app.cfg.Keys.Quit: if discordState != nil { if err := discordState.Close(); err != nil { slog.Error("failed to close the session", "err", err) } } - l.app.Stop() + app.Stop() case "Ctrl+C": // https://github.com/rivo/tview/blob/a64fc48d7654432f71922c8b908280cdb525805c/application.go#L153 return tcell.NewEventKey(tcell.KeyCtrlC, 0, tcell.ModNone) @@ -100,19 +100,19 @@ func (l *Layout) onAppInputCapture(event *tcell.EventKey) *tcell.EventKey { return event } -func (l *Layout) onFlexInputCapture(event *tcell.EventKey) *tcell.EventKey { +func (app *App) onFlexInputCapture(event *tcell.EventKey) *tcell.EventKey { switch event.Name() { - case l.cfg.Keys.FocusGuildsTree: - l.app.SetFocus(l.guildsTree) + case app.cfg.Keys.FocusGuildsTree: + app.SetFocus(app.guildsTree) return nil - case l.cfg.Keys.FocusMessagesText: - l.app.SetFocus(l.messagesText) + case app.cfg.Keys.FocusMessagesText: + app.SetFocus(app.messagesText) return nil - case l.cfg.Keys.FocusMessageInput: - l.app.SetFocus(l.messageInput) + case app.cfg.Keys.FocusMessageInput: + app.SetFocus(app.messageInput) return nil - case l.cfg.Keys.Logout: - l.app.Stop() + case app.cfg.Keys.Logout: + app.Stop() if err := keyring.Delete(consts.Name, "token"); err != nil { slog.Error("failed to delete token from keyring", "err", err) @@ -120,17 +120,17 @@ func (l *Layout) onFlexInputCapture(event *tcell.EventKey) *tcell.EventKey { } return nil - case l.cfg.Keys.ToggleGuildsTree: + case app.cfg.Keys.ToggleGuildsTree: // The guilds tree is visible if the numbers of items is two. - if l.flex.GetItemCount() == 2 { - l.flex.RemoveItem(l.guildsTree) + if app.flex.GetItemCount() == 2 { + app.flex.RemoveItem(app.guildsTree) - if l.guildsTree.HasFocus() { - l.app.SetFocus(l.flex) + if app.guildsTree.HasFocus() { + app.SetFocus(app.flex) } } else { - l.init() - l.app.SetFocus(l.guildsTree) + app.init() + app.SetFocus(app.guildsTree) } return nil diff --git a/cmd/guilds_tree.go b/cmd/guilds_tree.go index 2ebf3ac..899de4c 100644 --- a/cmd/guilds_tree.go +++ b/cmd/guilds_tree.go @@ -175,8 +175,8 @@ PARENT_CHANNELS: func (gt *GuildsTree) onSelected(n *tview.TreeNode) { gt.selectedChannelID = 0 - layout.messagesText.reset() - layout.messageInput.reset() + app.messagesText.reset() + app.messageInput.reset() if len(n.GetChildren()) != 0 { n.SetExpanded(!n.IsExpanded()) @@ -197,8 +197,8 @@ func (gt *GuildsTree) onSelected(n *tview.TreeNode) { gt.createChannelNodes(n, cs) case discord.ChannelID: - layout.messagesText.drawMsgs(ref) - layout.messagesText.ScrollToEnd() + app.messagesText.drawMsgs(ref) + app.messagesText.ScrollToEnd() c, err := discordState.Cabinet.Channel(ref) if err != nil { @@ -206,10 +206,10 @@ func (gt *GuildsTree) onSelected(n *tview.TreeNode) { return } - layout.messagesText.SetTitle(gt.channelToString(*c)) + app.messagesText.SetTitle(gt.channelToString(*c)) gt.selectedChannelID = ref - gt.app.SetFocus(layout.messageInput) + gt.app.SetFocus(app.messageInput) case nil: // Direct messages cs, err := discordState.PrivateChannels() if err != nil { diff --git a/cmd/message_input.go b/cmd/message_input.go index bab881d..d86c810 100644 --- a/cmd/message_input.go +++ b/cmd/message_input.go @@ -77,7 +77,7 @@ func (mi *MessageInput) onInputCapture(event *tcell.EventKey) *tcell.EventKey { } func (mi *MessageInput) send() { - if !layout.guildsTree.selectedChannelID.IsValid() { + if !app.guildsTree.selectedChannelID.IsValid() { return } @@ -99,16 +99,16 @@ func (mi *MessageInput) send() { } go func() { - if _, err := discordState.SendMessageComplex(layout.guildsTree.selectedChannelID, data); err != nil { - slog.Error("failed to send message in channel", "channel_id", layout.guildsTree.selectedChannelID, "err", err) + if _, err := discordState.SendMessageComplex(app.guildsTree.selectedChannelID, data); err != nil { + slog.Error("failed to send message in channel", "channel_id", app.guildsTree.selectedChannelID, "err", err) } }() mi.replyMessageID = 0 mi.reset() - layout.messagesText.Highlight() - layout.messagesText.ScrollToEnd() + app.messagesText.Highlight() + app.messagesText.ScrollToEnd() } func (mi *MessageInput) editor() { diff --git a/cmd/messages_text.go b/cmd/messages_text.go index 0d8823d..0477ff6 100644 --- a/cmd/messages_text.go +++ b/cmd/messages_text.go @@ -73,12 +73,12 @@ func (mt *MessagesText) drawMsgs(cID discord.ChannelID) { } for _, m := range slices.Backward(ms) { - layout.messagesText.createMessage(m) + app.messagesText.createMessage(m) } } func (mt *MessagesText) reset() { - layout.messagesText.selectedMessageID = 0 + app.messagesText.selectedMessageID = 0 mt.SetTitle("") mt.Clear() @@ -172,7 +172,7 @@ func (mt *MessagesText) getSelectedMessage() (*discord.Message, error) { return nil, errors.New("no message is currently selected") } - msg, err := discordState.Cabinet.Message(layout.guildsTree.selectedChannelID, mt.selectedMessageID) + msg, err := discordState.Cabinet.Message(app.guildsTree.selectedChannelID, mt.selectedMessageID) if err != nil { return nil, fmt.Errorf("could not retrieve selected message: %w", err) } @@ -181,7 +181,7 @@ func (mt *MessagesText) getSelectedMessage() (*discord.Message, error) { } func (mt *MessagesText) getSelectedMessageIndex() (int, error) { - ms, err := discordState.Cabinet.Messages(layout.guildsTree.selectedChannelID) + ms, err := discordState.Cabinet.Messages(app.guildsTree.selectedChannelID) if err != nil { return -1, err } @@ -215,9 +215,9 @@ func (mt *MessagesText) onInputCapture(event *tcell.EventKey) *tcell.EventKey { } func (mt *MessagesText) _select(name string) { - ms, err := discordState.Cabinet.Messages(layout.guildsTree.selectedChannelID) + ms, err := discordState.Cabinet.Messages(app.guildsTree.selectedChannelID) if err != nil { - slog.Error("failed to get messages", "err", err, "channel_id", layout.guildsTree.selectedChannelID) + slog.Error("failed to get messages", "err", err, "channel_id", app.guildsTree.selectedChannelID) return } @@ -341,9 +341,9 @@ func (mt *MessagesText) reply(mention bool) { } title += msg.Author.Tag() - layout.messageInput.SetTitle(title) - layout.messageInput.replyMessageID = mt.selectedMessageID - mt.app.SetFocus(layout.messageInput) + app.messageInput.SetTitle(title) + app.messageInput.replyMessageID = mt.selectedMessageID + mt.app.SetFocus(app.messageInput) } func (mt *MessagesText) delete() { @@ -355,7 +355,7 @@ func (mt *MessagesText) delete() { clientID := discordState.Ready().User.ID if msg.GuildID.IsValid() { - ps, err := discordState.Permissions(layout.guildsTree.selectedChannelID, discordState.Ready().User.ID) + ps, err := discordState.Permissions(app.guildsTree.selectedChannelID, discordState.Ready().User.ID) if err != nil { return } @@ -369,25 +369,25 @@ func (mt *MessagesText) delete() { } } - if err := discordState.DeleteMessage(layout.guildsTree.selectedChannelID, msg.ID, ""); err != nil { - slog.Error("failed to delete message", "err", err, "channel_id", layout.guildsTree.selectedChannelID, "message_id", msg.ID) + if err := discordState.DeleteMessage(app.guildsTree.selectedChannelID, msg.ID, ""); err != nil { + slog.Error("failed to delete message", "err", err, "channel_id", app.guildsTree.selectedChannelID, "message_id", msg.ID) return } - if err := discordState.MessageRemove(layout.guildsTree.selectedChannelID, msg.ID); err != nil { - slog.Error("failed to delete message", "err", err, "channel_id", layout.guildsTree.selectedChannelID, "message_id", msg.ID) + if err := discordState.MessageRemove(app.guildsTree.selectedChannelID, msg.ID); err != nil { + slog.Error("failed to delete message", "err", err, "channel_id", app.guildsTree.selectedChannelID, "message_id", msg.ID) return } - ms, err := discordState.Cabinet.Messages(layout.guildsTree.selectedChannelID) + ms, err := discordState.Cabinet.Messages(app.guildsTree.selectedChannelID) if err != nil { - slog.Error("failed to delete message", "err", err, "channel_id", layout.guildsTree.selectedChannelID) + slog.Error("failed to delete message", "err", err, "channel_id", app.guildsTree.selectedChannelID) return } mt.Clear() for _, m := range slices.Backward(ms) { - layout.messagesText.createMessage(m) + app.messagesText.createMessage(m) } } diff --git a/cmd/run.go b/cmd/run.go index fc91e42..05e9a90 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -11,7 +11,7 @@ import ( var ( discordState *State - layout *Layout + app *App ) func Run(token string) error { @@ -34,6 +34,6 @@ func Run(token string) error { return err } - layout = newLayout(cfg) - return layout.run(token) + app = newApp(cfg) + return app.run(token) } diff --git a/cmd/state.go b/cmd/state.go index 91c3809..4ecca24 100644 --- a/cmd/state.go +++ b/cmd/state.go @@ -6,7 +6,6 @@ import ( "runtime" "slices" - "github.com/ayn2op/discordo/internal/config" "github.com/diamondburned/arikawa/v3/api" "github.com/diamondburned/arikawa/v3/discord" "github.com/diamondburned/arikawa/v3/gateway" @@ -18,29 +17,25 @@ import ( type State struct { *ningen.State - cfg *config.Config - app *tview.Application } -func openState(token string, app *tview.Application, cfg *config.Config) error { - api.UserAgent = cfg.UserAgent +func openState(token string) error { + api.UserAgent = app.cfg.UserAgent gateway.DefaultIdentity = gateway.IdentifyProperties{ OS: runtime.GOOS, Device: "", - Browser: cfg.Browser, - BrowserVersion: cfg.BrowserVersion, - BrowserUserAgent: cfg.UserAgent, + Browser: app.cfg.Browser, + BrowserVersion: app.cfg.BrowserVersion, + BrowserUserAgent: app.cfg.UserAgent, } gateway.DefaultPresence = &gateway.UpdatePresenceCommand{ - Status: cfg.Status, + Status: app.cfg.Status, } discordState = &State{ State: ningen.New(token), - cfg: cfg, - app: app, } // Handlers @@ -62,11 +57,11 @@ func (s *State) onRequest(r httpdriver.Request) error { } func (s *State) onReady(r *gateway.ReadyEvent) { - root := layout.guildsTree.GetRoot() + root := app.guildsTree.GetRoot() root.ClearChildren() dmNode := tview.NewTreeNode("Direct Messages") - dmNode.SetColor(tcell.GetColor(s.cfg.Theme.GuildsTree.PrivateChannelColor)) + dmNode.SetColor(tcell.GetColor(app.cfg.Theme.GuildsTree.PrivateChannelColor)) root.AddChild(dmNode) // Track guilds that have a parent (folder) to add orphan channels later @@ -78,32 +73,32 @@ func (s *State) onReady(r *gateway.ReadyEvent) { } folderGuildIds = append(folderGuildIds, folder.GuildIDs...) - layout.guildsTree.createFolderNode(folder) + app.guildsTree.createFolderNode(folder) } // add orphan (without folder) guilds to guilds tree for _, guild := range r.Guilds { if !slices.Contains(folderGuildIds, guild.ID) { - layout.guildsTree.createGuildNode(root, guild.Guild) + app.guildsTree.createGuildNode(root, guild.Guild) } } - layout.guildsTree.SetCurrentNode(root) - s.app.SetFocus(layout.guildsTree) + app.guildsTree.SetCurrentNode(root) + app.SetFocus(app.guildsTree) } func (s *State) onMessageCreate(m *gateway.MessageCreateEvent) { - if layout.guildsTree.selectedChannelID.IsValid() && layout.guildsTree.selectedChannelID == m.ChannelID { - layout.messagesText.createMessage(m.Message) + if app.guildsTree.selectedChannelID.IsValid() && app.guildsTree.selectedChannelID == m.ChannelID { + app.messagesText.createMessage(m.Message) } } func (s *State) onMessageDelete(m *gateway.MessageDeleteEvent) { - if layout.guildsTree.selectedChannelID == m.ChannelID { - layout.messagesText.selectedMessageID = 0 - layout.messagesText.Highlight() - layout.messagesText.Clear() + if app.guildsTree.selectedChannelID == m.ChannelID { + app.messagesText.selectedMessageID = 0 + app.messagesText.Highlight() + app.messagesText.Clear() - layout.messagesText.drawMsgs(m.ChannelID) + app.messagesText.drawMsgs(m.ChannelID) } }