From a2be9c3329c8c4c783d30757793beb0423643fe8 Mon Sep 17 00:00:00 2001 From: Ayyan Date: Tue, 25 Mar 2025 23:20:03 -0400 Subject: [PATCH] feat: floating url list (#520) --- cmd/app.go | 24 ++++++++---- cmd/messages_text.go | 86 ++++++++++++++++++------------------------ internal/login/form.go | 10 +---- internal/ui/util.go | 10 +++++ 4 files changed, 65 insertions(+), 65 deletions(-) create mode 100644 internal/ui/util.go diff --git a/cmd/app.go b/cmd/app.go index f70d565..c355b7e 100644 --- a/cmd/app.go +++ b/cmd/app.go @@ -16,6 +16,7 @@ type App struct { cfg *config.Config + pages *tview.Pages flex *tview.Flex guildsTree *GuildsTree messagesText *MessagesText @@ -29,6 +30,7 @@ func newApp(cfg *config.Config) *App { cfg: cfg, + pages: tview.NewPages(), flex: tview.NewFlex(), guildsTree: newGuildsTree(app, cfg), messagesText: newMessagesText(app, cfg), @@ -57,7 +59,7 @@ func (app *App) show(token string) error { } app.init() - app.SetRoot(app.flex, true) + app.SetRoot(app.pages, true) } return nil @@ -71,16 +73,24 @@ func (app *App) run(token string) error { return app.Run() } -func (app *App) init() { - app.flex.Clear() +func (a *App) clearPages() { + for _, name := range a.pages.GetPageNames(false) { + a.pages.RemovePage(name) + } +} + +func (a *App) init() { + a.clearPages() + a.flex.Clear() right := tview.NewFlex() right.SetDirection(tview.FlexRow) - right.AddItem(app.messagesText, 0, 1, false) - right.AddItem(app.messageInput, 3, 1, false) + right.AddItem(a.messagesText, 0, 1, false) + right.AddItem(a.messageInput, 3, 1, false) // The guilds tree is always focused first at start-up. - app.flex.AddItem(app.guildsTree, 0, 1, true) - app.flex.AddItem(right, 0, 4, false) + a.flex.AddItem(a.guildsTree, 0, 1, true) + a.flex.AddItem(right, 0, 4, false) + a.pages.AddAndSwitchToPage("flex", a.flex, true) } func (app *App) onInputCapture(event *tcell.EventKey) *tcell.EventKey { diff --git a/cmd/messages_text.go b/cmd/messages_text.go index 5854135..a73adf4 100644 --- a/cmd/messages_text.go +++ b/cmd/messages_text.go @@ -12,6 +12,7 @@ import ( "github.com/atotto/clipboard" "github.com/ayn2op/discordo/internal/config" "github.com/ayn2op/discordo/internal/markdown" + "github.com/ayn2op/discordo/internal/ui" "github.com/diamondburned/arikawa/v3/discord" "github.com/diamondburned/ningen/v3/discordmd" "github.com/gdamore/tcell/v2" @@ -330,10 +331,9 @@ func (mt *MessagesText) open() { } else { go openURL(msg.Attachments[0].URL) } - return + } else { + mt.showUrlSelector(urls, msg.Attachments) } - - showSelector(mt, urls, msg.Attachments) } func extractURLs(content string) []string { @@ -359,17 +359,43 @@ func extractURLs(content string) []string { return urls } -func showSelector(mt *MessagesText, urls []string, attachments []discord.Attachment) { +func (mt *MessagesText) showUrlSelector(urls []string, attachments []discord.Attachment) { + done := func() { + app.pages.RemovePage("list").SwitchToPage("flex") + app.SetFocus(app.messagesText) + } + list := tview.NewList(). SetWrapAround(true). SetHighlightFullLine(true). - ShowSecondaryText(false) + ShowSecondaryText(false). + SetDoneFunc(done) + + p := mt.cfg.Theme.BorderPadding + list. + SetBorder(mt.cfg.Theme.Border). + SetBorderColor(tcell.GetColor(mt.cfg.Theme.BorderColor)). + SetBorderPadding(p[0], p[1], p[2], p[3]). + SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + switch event.Name() { + case mt.cfg.Keys.MessagesText.SelectPrevious: + return tcell.NewEventKey(tcell.KeyUp, 0, tcell.ModNone) + case mt.cfg.Keys.MessagesText.SelectNext: + return tcell.NewEventKey(tcell.KeyDown, 0, tcell.ModNone) + case mt.cfg.Keys.MessagesText.SelectFirst: + return tcell.NewEventKey(tcell.KeyHome, 0, tcell.ModNone) + case mt.cfg.Keys.MessagesText.SelectLast: + return tcell.NewEventKey(tcell.KeyEnd, 0, tcell.ModNone) + } + + return event + }) for i, a := range attachments { attachment := a list.AddItem(a.Filename, "", rune('a'+i), func() { go openURL(attachment.URL) - app.SetRoot(app.flex, true) + done() }) } @@ -377,53 +403,13 @@ func showSelector(mt *MessagesText, urls []string, attachments []discord.Attachm urlCopy := url list.AddItem(url, "", rune('1'+i), func() { go openURL(urlCopy) - app.SetRoot(app.flex, true) + done() }) } - list.AddItem("Cancel", "", 'q', func() { - app.SetRoot(app.flex, true) - }) - - list.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { - switch event.Name() { - case mt.cfg.Keys.MessagesText.SelectPrevious: - return tcell.NewEventKey(tcell.KeyUp, 0, tcell.ModNone) - case mt.cfg.Keys.MessagesText.SelectNext: - return tcell.NewEventKey(tcell.KeyDown, 0, tcell.ModNone) - case mt.cfg.Keys.MessagesText.SelectFirst: - list.SetCurrentItem(0) - return nil - case mt.cfg.Keys.MessagesText.SelectLast: - list.SetCurrentItem(list.GetItemCount() - 1) - return nil - case "Escape": - app.SetRoot(app.flex, true) - return nil - } - return event - }) - - height := len(urls) + len(attachments) + 1 - maxHeight := 20 - if height > maxHeight { - height = maxHeight - } - - modal := createCenteredModal(list, height, 60) - - app.SetRoot(modal, true) - app.SetFocus(list) -} - -func createCenteredModal(p tview.Primitive, height, width int) tview.Primitive { - return tview.NewFlex(). - AddItem(nil, 0, 1, false). - AddItem(tview.NewFlex().SetDirection(tview.FlexRow). - AddItem(nil, 0, 1, false). - AddItem(p, height, 1, true). - AddItem(nil, 0, 1, false), width, 1, true). - AddItem(nil, 0, 1, false) + app.pages. + AddAndSwitchToPage("list", ui.Centered(list, 0, 0), true). + ShowPage("flex") } func openURL(url string) { diff --git a/internal/login/form.go b/internal/login/form.go index 592aa8f..1575fe9 100644 --- a/internal/login/form.go +++ b/internal/login/form.go @@ -7,6 +7,7 @@ import ( "github.com/ayn2op/discordo/internal/config" "github.com/ayn2op/discordo/internal/consts" + "github.com/ayn2op/discordo/internal/ui" "github.com/diamondburned/arikawa/v3/api" "github.com/diamondburned/arikawa/v3/utils/httputil" "github.com/rivo/tview" @@ -105,13 +106,6 @@ func (f *Form) onError(err error) { f.RemovePage("modal").SwitchToPage("form") }) f. - AddAndSwitchToPage("modal", centered(modal, 0, 0), true). + AddAndSwitchToPage("modal", ui.Centered(modal, 0, 0), true). ShowPage("form") } - -func centered(p tview.Primitive, width, height int) tview.Primitive { - return tview.NewGrid(). - SetColumns(0, width, 0). - SetRows(0, height, 0). - AddItem(p, 1, 1, 1, 1, 0, 0, true) -} diff --git a/internal/ui/util.go b/internal/ui/util.go new file mode 100644 index 0000000..b989a7b --- /dev/null +++ b/internal/ui/util.go @@ -0,0 +1,10 @@ +package ui + +import "github.com/rivo/tview" + +func Centered(p tview.Primitive, width, height int) tview.Primitive { + return tview.NewGrid(). + SetColumns(0, width, 0). + SetRows(0, height, 0). + AddItem(p, 1, 1, 1, 1, 0, 0, true) +}