Revert "feat: show error modal on errors (#621)"

This reverts commit dfaaf10818.
This commit is contained in:
ayn2op 2025-11-22 13:38:39 -05:00
parent 97b2249608
commit db9e64fc50
5 changed files with 55 additions and 93 deletions

View file

@ -2,8 +2,6 @@ package cmd
import (
"log/slog"
"strings"
"fmt"
"github.com/ayn2op/discordo/internal/config"
"github.com/ayn2op/discordo/internal/keyring"
@ -11,14 +9,13 @@ import (
"github.com/ayn2op/discordo/internal/ui"
"github.com/ayn2op/tview"
"github.com/gdamore/tcell/v2"
"golang.design/x/clipboard"
)
const (
flexPageName = "flex"
mentionsListPageName = "mentionsList"
attachmentsListPageName = "attachmentsList"
modalPageName = "modalPageName"
confirmModalPageName = "confirmModal"
)
type application struct {
@ -134,7 +131,7 @@ func (a *application) onPagesInputCapture(event *tcell.EventKey) *tcell.EventKey
a.quit()
if err := keyring.DeleteToken(); err != nil {
a.onError("Failed to delete token from keyring", err)
slog.Error("failed to delete token from keyring", "err", err)
return nil
}
@ -205,60 +202,22 @@ func (a *application) focusNext() {
}
}
func (a *application) onError(msg string, err error, info ...any) {
slog.Error(msg, append(info, "err", err)...)
a.showErrorModal(msg, err.Error(), info...)
}
func (a *application) showModal(title, prompt string, buttons []string, onDone func(label string)) {
func (a *application) showConfirmModal(prompt string, buttons []string, onDone func(label string)) {
previousFocus := a.GetFocus()
modal := tview.NewModal()
modal.Box = ui.ConfigureBox(modal.Box, &a.cfg.Theme)
modal.
modal := tview.NewModal().
SetText(prompt).
AddButtons(buttons).
SetDoneFunc(func(_ int, buttonLabel string) {
a.pages.
RemovePage(modalPageName).
SwitchToPage(flexPageName)
a.pages.RemovePage(confirmModalPageName).SwitchToPage(flexPageName)
a.SetFocus(previousFocus)
if onDone != nil {
onDone(buttonLabel)
}
}).
SetTitle(title).
SetTitleAlignment(tview.AlignmentCenter)
})
a.pages.
AddAndSwitchToPage(modalPageName, ui.Centered(modal, 0, 0), true).
AddAndSwitchToPage(confirmModalPageName, ui.Centered(modal, 0, 0), true).
ShowPage(flexPageName)
a.SetFocus(modal)
}
func (a *application) showConfirmModal(prompt string, buttons []string, onDone func(label string)) {
a.showModal("", prompt, buttons, onDone)
}
func (a *application) showErrorModal(msg, err string, info ...any) {
a.showModal("[ ERROR ]", msg + "\nReason: " + err, []string{"Copy", "OK"}, func(label string) {
if label != "Copy" {
return
}
res := &strings.Builder{}
fmt.Fprintf(res, "%s\nReason: %s", msg, err)
for i := 0; i < len(info)-1; i += 2 {
fmt.Fprintf(res, "\n%v: %#v", info[i], info[i+1])
}
// Do as log/slog does. "!BADKEY" for last odd argument.
if (len(info) % 2) == 1 {
fmt.Fprintf(res, "\n!BADKEY: %#v", info[len(info)-1])
}
go clipboard.Write(clipboard.FmtText, []byte(res.String()))
})
}
func (a *application) showInfoModal(text string) {
a.showModal("[ INFO ]", text, []string{"OK"}, nil)
}

View file

@ -2,6 +2,7 @@ package cmd
import (
"fmt"
"log/slog"
"sort"
"github.com/ayn2op/discordo/internal/config"
@ -52,7 +53,7 @@ func (gt *guildsTree) createFolderNode(folder gateway.GuildFolder) {
for _, gID := range folder.GuildIDs {
guild, err := discordState.Cabinet.Guild(gID)
if err != nil {
app.onError("Failed to get guild from state", err, "guild_id", gID)
slog.Error("failed to get guild from state", "guild_id", gID, "err", err)
continue
}
@ -155,7 +156,7 @@ func (gt *guildsTree) onSelected(node *tview.TreeNode) {
channels, err := discordState.Cabinet.Channels(ref)
if err != nil {
app.onError("Failed to get channels", err, "guild_id", ref)
slog.Error("failed to get channels", "err", err, "guild_id", ref)
return
}
@ -167,7 +168,7 @@ func (gt *guildsTree) onSelected(node *tview.TreeNode) {
case discord.ChannelID:
channel, err := discordState.Cabinet.Channel(ref)
if err != nil {
app.onError("Failed to get channel", err, "channel_id", ref)
slog.Error("failed to get channel", "channel_id", ref)
return
}
@ -175,7 +176,7 @@ func (gt *guildsTree) onSelected(node *tview.TreeNode) {
messages, err := discordState.Messages(channel.ID, uint(gt.cfg.MessagesLimit))
if err != nil {
app.onError("Failed to get messages", err, "channel_id", channel.ID, "limit", gt.cfg.MessagesLimit)
slog.Error("failed to get messages", "err", err, "channel_id", channel.ID, "limit", gt.cfg.MessagesLimit)
return
}
@ -202,7 +203,7 @@ func (gt *guildsTree) onSelected(node *tview.TreeNode) {
case nil: // Direct messages
channels, err := discordState.PrivateChannels()
if err != nil {
app.onError("Failed to get private channels", err)
slog.Error("failed to get private channels", "err", err)
return
}

View file

@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"io"
"log/slog"
"os"
"os/exec"
"path/filepath"
@ -59,7 +60,7 @@ func newMessageInput(cfg *config.Config) *messageInput {
}
if err := clipboard.Init(); err != nil {
app.onError("Failed to init clipboard", err)
slog.Warn("failed to init clipboard", "err", err)
} else {
mi.
SetClipboard(func(s string) {
@ -175,13 +176,13 @@ func (mi *messageInput) send() {
if mi.edit {
m, err := app.messagesList.selectedMessage()
if err != nil {
app.onError("Failed to get selected message", err)
slog.Error("failed to get selected message", "err", err)
return
}
data := api.EditMessageData{Content: option.NewNullableString(text)}
if _, err := discordState.EditMessageComplex(m.ChannelID, m.ID, data); err != nil {
app.onError("Failed to edit message", err)
slog.Error("failed to edit message", "err", err)
}
mi.edit = false
@ -189,7 +190,7 @@ func (mi *messageInput) send() {
data := mi.sendMessageData
data.Content = text
if _, err := discordState.SendMessageComplex(app.guildsTree.selectedChannelID, *data); err != nil {
app.onError("Failed to send message in channel", err, "channel_id", app.guildsTree.selectedChannelID)
slog.Error("failed to send message in channel", "channel_id", app.guildsTree.selectedChannelID, "err", err)
}
}
@ -271,7 +272,7 @@ func (mi *messageInput) tabComplete(isAuto bool) {
members, err := discordState.Cabinet.Members(gID)
if err != nil {
app.onError("Failed to get members from state", err, "guild_id", gID)
slog.Error("failed to get members from state", "guild_id", gID, "err", err)
return
}
@ -318,7 +319,7 @@ func (mi *messageInput) tabComplete(isAuto bool) {
mi.mentionsList.Clear()
mems, err := discordState.Cabinet.Members(gID)
if err != nil {
app.onError("Fetching members failed", err)
slog.Error("fetching members failed", "err", err)
return
}
res := fuzzy.FindFrom(name, memberList(mems))
@ -348,7 +349,7 @@ func (m memberList) Len() int { return len(m) }
func channelHasUser(cID discord.ChannelID, id discord.UserID) bool {
perms, err := discordState.Permissions(cID, id)
if err != nil {
app.onError("Can't get permissions", err, "channel", cID, "user", id)
slog.Error("can't get permissions", "channel", cID, "user", id)
return false
}
return perms.Has(discord.PermissionViewChannel)
@ -439,7 +440,7 @@ func (mi *messageInput) addMentionItem(gID discord.GuildID, m *discord.Member) b
presence, err := discordState.Cabinet.Presence(gID, m.User.ID)
if err != nil {
app.onError("Failed to get presence from state", err, "guild_id", gID, "user_id", m.User.ID)
slog.Info("failed to get presence from state", "guild_id", gID, "user_id", m.User.ID, "err", err)
}
if presence != nil && presence.Status == discord.OfflineStatus {
@ -467,7 +468,7 @@ func (mi *messageInput) stopTabCompletion() {
func (mi *messageInput) editor() {
file, err := os.CreateTemp("", tmpFilePattern)
if err != nil {
app.onError("Failed to create tmp file", err)
slog.Error("failed to create tmp file", "err", err)
return
}
defer file.Close()
@ -483,14 +484,14 @@ func (mi *messageInput) editor() {
app.Suspend(func() {
err := cmd.Run()
if err != nil {
app.onError("Failed to run command", err, "args", cmd.Args)
slog.Error("failed to run command", "args", cmd.Args, "err", err)
return
}
})
msg, err := os.ReadFile(file.Name())
if err != nil {
app.onError("Failed to read tmp file", err, "name", file.Name())
slog.Error("failed to read tmp file", "name", file.Name(), "err", err)
return
}
@ -513,14 +514,14 @@ func (mi *messageInput) openFilePicker() {
paths, err := zenity.SelectFileMultiple()
if err != nil {
app.onError("Failed to open file dialog", err)
slog.Error("failed to open file dialog", "err", err)
return
}
for _, path := range paths {
file, err := os.Open(path)
if err != nil {
app.onError("Failed to open file", err, "path", path)
slog.Error("failed to open file", "path", path, "err", err)
continue
}

View file

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
"log/slog"
"net/http"
"os"
"path/filepath"
@ -144,7 +145,7 @@ func (ml *messagesList) drawAuthor(message discord.Message) {
if message.GuildID.IsValid() {
member, err := discordState.Cabinet.Member(message.GuildID, message.Author.ID)
if err != nil {
app.onError("Failed to get member from state", err, "guild_id", message.GuildID, "user", message.Author)
slog.Error("failed to get member from state", "guild_id", message.GuildID, "member_id", message.Author.ID, "err", err)
} else {
if member.Nick != "" {
name = member.Nick
@ -293,13 +294,13 @@ func (ml *messagesList) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
func (ml *messagesList) _select(name string) {
ms, err := discordState.Cabinet.Messages(app.guildsTree.selectedChannelID)
if err != nil {
app.onError("Failed to get messages", err, "channel_id", app.guildsTree.selectedChannelID)
slog.Error("failed to get messages", "err", err, "channel_id", app.guildsTree.selectedChannelID)
return
}
msgIdx, err := ml.selectedMessageIndex()
if err != nil {
app.onError("Failed to get selected message", err)
slog.Error("failed to get selected message", "err", err)
return
}
@ -348,7 +349,7 @@ func (ml *messagesList) onHighlighted(added, removed, remaining []string) {
if len(added) > 0 {
id, err := discord.ParseSnowflake(added[0])
if err != nil {
app.onError("Failed to parse region id as int to use as message id", err)
slog.Error("Failed to parse region id as int to use as message id.", "err", err)
return
}
@ -359,7 +360,7 @@ func (ml *messagesList) onHighlighted(added, removed, remaining []string) {
func (ml *messagesList) yankID() {
msg, err := ml.selectedMessage()
if err != nil {
app.onError("Failed to get selected message", err)
slog.Error("failed to get selected message", "err", err)
return
}
@ -369,7 +370,7 @@ func (ml *messagesList) yankID() {
func (ml *messagesList) yankContent() {
msg, err := ml.selectedMessage()
if err != nil {
app.onError("Failed to get selected message", err)
slog.Error("failed to get selected message", "err", err)
return
}
@ -379,7 +380,7 @@ func (ml *messagesList) yankContent() {
func (ml *messagesList) yankURL() {
msg, err := ml.selectedMessage()
if err != nil {
app.onError("Failed to get selected message", err)
slog.Error("failed to get selected message", "err", err)
return
}
@ -389,7 +390,7 @@ func (ml *messagesList) yankURL() {
func (ml *messagesList) open() {
msg, err := ml.selectedMessage()
if err != nil {
app.onError("Failed to get selected message", err)
slog.Error("failed to get selected message", "err", err)
return
}
@ -491,45 +492,45 @@ func (ml *messagesList) showAttachmentsList(urls []string, attachments []discord
func (ml *messagesList) openAttachment(attachment discord.Attachment) {
resp, err := http.Get(attachment.URL)
if err != nil {
app.onError("Failed to fetch the attachment", err, "url", attachment.URL)
slog.Error("failed to fetch the attachment", "err", err, "url", attachment.URL)
}
defer resp.Body.Close()
path := filepath.Join(consts.CacheDir(), "attachments")
if err := os.MkdirAll(path, os.ModePerm); err != nil {
app.onError("Failed to create attachments dir", err, "path", path)
slog.Error("failed to create attachments dir", "err", err, "path", path)
return
}
path = filepath.Join(path, attachment.Filename)
file, err := os.Create(path)
if err != nil {
app.onError("Failed to create attachment file", err, "path", path)
slog.Error("failed to create attachment file", "err", err, "path", path)
return
}
defer file.Close()
if _, err := io.Copy(file, resp.Body); err != nil {
app.onError("Failed to copy attachment to file", err)
slog.Error("failed to copy attachment to file", "err", err)
return
}
if err := open.Start(path); err != nil {
app.onError("Failed to open attachment file", err, "path", path)
slog.Error("failed to open attachment file", "err", err, "path", path)
return
}
}
func (ml *messagesList) openURL(url string) {
if err := open.Start(url); err != nil {
app.onError("Failed to open URL", err, "url", url)
slog.Error("failed to open URL", "err", err, "url", url)
}
}
func (ml *messagesList) reply(mention bool) {
msg, err := ml.selectedMessage()
if err != nil {
app.onError("Failed to get selected message", err)
slog.Error("failed to get selected message", "err", err)
return
}
@ -537,7 +538,7 @@ func (ml *messagesList) reply(mention bool) {
if msg.GuildID.IsValid() {
member, err := discordState.Cabinet.Member(msg.GuildID, msg.Author.ID)
if err != nil {
app.onError("Failed to get member from state", err, "guild_id", msg.GuildID, "member_id", msg.Author.ID)
slog.Error("failed to get member from state", "guild_id", msg.GuildID, "member_id", msg.Author.ID, "err", err)
} else {
if member.Nick != "" {
name = member.Nick
@ -563,18 +564,18 @@ func (ml *messagesList) reply(mention bool) {
func (ml *messagesList) edit() {
message, err := ml.selectedMessage()
if err != nil {
app.onError("Failed to get selected message", err)
slog.Error("failed to get selected message", "err", err)
return
}
me, err := discordState.Cabinet.Me()
if err != nil {
app.onError("Failed to get client user (me)", err)
slog.Error("failed to get client user (me)", "err", err)
return
}
if message.Author.ID != me.ID {
app.onError("Failed to edit message", errors.New("You are not the author"), "channel_id", message.ChannelID, "message_id", message.ID)
slog.Error("failed to edit message; not the author", "channel_id", message.ChannelID, "message_id", message.ID)
return
}
@ -601,25 +602,25 @@ func (ml *messagesList) confirmDelete() {
func (ml *messagesList) delete() {
msg, err := ml.selectedMessage()
if err != nil {
app.onError("Failed to get selected message", err)
slog.Error("failed to get selected message", "err", err)
return
}
if msg.GuildID.IsValid() {
me, err := discordState.Cabinet.Me()
if err != nil {
app.onError("Failed to get client user (me)", err)
slog.Error("failed to get client user (me)", "err", err)
return
}
if msg.Author.ID != me.ID && !discordState.HasPermissions(msg.ChannelID, discord.PermissionManageMessages) {
app.onError("Failed to delete message", errors.New("Permission denied."), "channel_id", msg.ChannelID, "message_id", msg.ID)
slog.Error("failed to delete message; missing relevant permissions", "channel_id", msg.ChannelID, "message_id", msg.ID)
return
}
}
if err := discordState.DeleteMessage(app.guildsTree.selectedChannelID, msg.ID, ""); err != nil {
app.onError("Failed to delete message", err, "channel_id", app.guildsTree.selectedChannelID, "message_id", msg.ID)
slog.Error("failed to delete message", "channel_id", app.guildsTree.selectedChannelID, "message_id", msg.ID, "err", err)
return
}
@ -627,7 +628,7 @@ func (ml *messagesList) delete() {
ml.Highlight()
if err := discordState.MessageRemove(app.guildsTree.selectedChannelID, msg.ID); err != nil {
app.onError("Failed to delete message", err, "channel_id", app.guildsTree.selectedChannelID, "message_id", msg.ID)
slog.Error("failed to delete message", "channel_id", app.guildsTree.selectedChannelID, "message_id", msg.ID, "err", err)
return
}
@ -649,7 +650,7 @@ func (ml *messagesList) requestGuildMembers(gID discord.GuildID, ms []discord.Me
UserIDs: slices.Compact(usersToFetch),
})
if err != nil {
app.onError("Failed to request guild members", err, "guild_id", gID)
slog.Error("failed to request guild members", "guild_id", gID, "err", err)
return
}

View file

@ -152,7 +152,7 @@ func onMessageCreate(message *gateway.MessageCreateEvent) {
}
if err := notifications.Notify(discordState, message, app.cfg); err != nil {
app.onError("Notification failed", err)
slog.Error("Notification failed", "err", err)
}
}
@ -166,7 +166,7 @@ func onMessageDelete(message *gateway.MessageDeleteEvent) {
if app.guildsTree.selectedChannelID == message.ChannelID {
messages, err := discordState.Cabinet.Messages(message.ChannelID)
if err != nil {
app.onError("Failed to get messages from state", err, "channel_id", message.ChannelID)
slog.Error("failed to get messages from state", "err", err, "channel_id", message.ChannelID)
return
}