diff --git a/README.md b/README.md index 2d392da..6efaf24 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Discordo is a lightweight, secure, and feature-rich Discord terminal client. Hea - Lightweight - Configurable - Mouse & clipboard support +- Attachments - Notifications - 2-Factor authentication - Discord-flavored markdown diff --git a/cmd/message_input.go b/cmd/message_input.go index 4ee8f46..1688d41 100644 --- a/cmd/message_input.go +++ b/cmd/message_input.go @@ -1,9 +1,12 @@ package cmd import ( + "fmt" + "io" "log/slog" "os" "os/exec" + "path/filepath" "regexp" "slices" "strings" @@ -18,9 +21,10 @@ import ( "github.com/diamondburned/arikawa/v3/api" "github.com/diamondburned/arikawa/v3/discord" "github.com/diamondburned/arikawa/v3/state" - "github.com/diamondburned/arikawa/v3/utils/json/option" + "github.com/diamondburned/arikawa/v3/utils/sendpart" "github.com/diamondburned/ningen/v3/discordmd" "github.com/gdamore/tcell/v2" + "github.com/ncruces/zenity" "github.com/sahilm/fuzzy" "github.com/yuin/goldmark/ast" ) @@ -33,20 +37,22 @@ type messageInput struct { *tview.TextArea cfg *config.Config - cache *cache.Cache - mentionsList *tview.List - replyMessageID discord.MessageID - lastSearch time.Time + sendMessageData *api.SendMessageData + cache *cache.Cache + mentionsList *tview.List + lastSearch time.Time } type memberList []discord.Member func newMessageInput(cfg *config.Config) *messageInput { mi := &messageInput{ - TextArea: tview.NewTextArea(), - cfg: cfg, - cache: cache.NewCache(), - mentionsList: tview.NewList(), + TextArea: tview.NewTextArea(), + cfg: cfg, + + sendMessageData: &api.SendMessageData{}, + cache: cache.NewCache(), + mentionsList: tview.NewList(), } mi.Box = ui.ConfigureBox(mi.Box, &cfg.Theme) @@ -75,7 +81,7 @@ func newMessageInput(cfg *config.Config) *messageInput { } func (mi *messageInput) reset() { - mi.replyMessageID = 0 + mi.sendMessageData = &api.SendMessageData{} mi.SetTitle("") mi.SetText("", true) } @@ -90,10 +96,14 @@ func (mi *messageInput) onInputCapture(event *tcell.EventKey) *tcell.EventKey { mi.send() return nil - case mi.cfg.Keys.MessageInput.Editor: + case mi.cfg.Keys.MessageInput.OpenEditor: mi.stopTabCompletion() mi.editor() return nil + case mi.cfg.Keys.MessageInput.OpenFilePicker: + mi.stopTabCompletion() + mi.openFilePicker() + return nil case mi.cfg.Keys.MessageInput.Cancel: if app.pages.GetVisibile(mentionsListPageName) { mi.stopTabCompletion() @@ -135,31 +145,22 @@ func (mi *messageInput) send() { return } - text := strings.TrimSpace(mi.GetText()) - if text == "" { - return + data := mi.sendMessageData + if text := strings.TrimSpace(mi.GetText()); text != "" { + data.Content = processText(app.guildsTree.selectedChannelID, []byte(text)) } - // Process mentions (there's no shortcut, just parse the entire message - // as markdown and then expand non-code mentions) - data := api.SendMessageData{ - Content: processText(app.guildsTree.selectedChannelID, []byte(text)), + 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) } - if mi.replyMessageID != 0 { - data.Reference = &discord.MessageReference{MessageID: mi.replyMessageID} - data.AllowedMentions = &api.AllowedMentions{RepliedUser: option.False} - if strings.HasPrefix(mi.GetTitle(), "[@]") { - data.AllowedMentions.RepliedUser = option.True + // Close the attached files after sending the message. + for _, file := range mi.sendMessageData.Files { + if closer, ok := file.Reader.(io.Closer); ok { + _ = closer.Close() } } - go func() { - 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.reset() app.messagesList.Highlight() app.messagesList.ScrollToEnd() @@ -470,3 +471,38 @@ func (mi *messageInput) editor() { mi.SetText(strings.TrimSpace(string(msg)), true) } + +func (mi *messageInput) addTitle(s string) { + title := mi.GetTitle() + if title != "" { + title += " | " + } + + mi.SetTitle(title + s) +} + +func (mi *messageInput) openFilePicker() { + if !app.guildsTree.selectedChannelID.IsValid() { + return + } + + paths, err := zenity.SelectFileMultiple() + if err != nil { + slog.Error("failed to open file dialog", "err", err) + return + } + + for _, path := range paths { + file, err := os.Open(path) + if err != nil { + slog.Error("failed to open file", "path", path, "err", err) + continue + } + + name := filepath.Base(path) + mi.sendMessageData.Files = append(mi.sendMessageData.Files, sendpart.File{Name: name, Reader: file}) + + title := fmt.Sprintf("Attached %s", name) + mi.addTitle(title) + } +} diff --git a/cmd/messages_list.go b/cmd/messages_list.go index db6aa98..b5ab74d 100644 --- a/cmd/messages_list.go +++ b/cmd/messages_list.go @@ -15,9 +15,11 @@ import ( "github.com/ayn2op/discordo/internal/markdown" "github.com/ayn2op/discordo/internal/ui" "github.com/ayn2op/tview" + "github.com/diamondburned/arikawa/v3/api" "github.com/diamondburned/arikawa/v3/discord" "github.com/diamondburned/arikawa/v3/gateway" "github.com/diamondburned/arikawa/v3/state" + "github.com/diamondburned/arikawa/v3/utils/json/option" "github.com/diamondburned/ningen/v3/discordmd" "github.com/gdamore/tcell/v2" "github.com/skratchdot/open-golang/open" @@ -81,8 +83,6 @@ func (ml *messagesList) drawMsgs(cID discord.ChannelID) { func (ml *messagesList) reset() { ml.selectedMessageID = 0 - app.messageInput.replyMessageID = 0 - ml. Clear(). Highlight(). @@ -267,7 +267,6 @@ func (ml *messagesList) onInputCapture(event *tcell.EventKey) *tcell.EventKey { switch event.Name() { case ml.cfg.Keys.MessagesList.Cancel: ml.selectedMessageID = 0 - app.messageInput.replyMessageID = 0 ml.Highlight() case ml.cfg.Keys.MessagesList.SelectPrevious, ml.cfg.Keys.MessagesList.SelectNext, ml.cfg.Keys.MessagesList.SelectFirst, ml.cfg.Keys.MessagesList.SelectLast, ml.cfg.Keys.MessagesList.SelectReply: @@ -493,13 +492,6 @@ func openURL(url string) { } func (ml *messagesList) reply(mention bool) { - var title string - if mention { - title += "[@] Replying to " - } else { - title += "Replying to " - } - msg, err := ml.selectedMsg() if err != nil { slog.Error("failed to get selected message", "err", err) @@ -518,9 +510,18 @@ func (ml *messagesList) reply(mention bool) { name = ui.PreferredName(msg.Author, ml.cfg.Theme) } - title += name - app.messageInput.SetTitle(title) - app.messageInput.replyMessageID = ml.selectedMessageID + data := app.messageInput.sendMessageData + data.Reference = &discord.MessageReference{MessageID: ml.selectedMessageID} + data.AllowedMentions = &api.AllowedMentions{RepliedUser: option.False} + + title := "Replying to " + if mention { + data.AllowedMentions.RepliedUser = option.True + title = "[@] " + title + } + + app.messageInput.sendMessageData = data + app.messageInput.addTitle(title + name) app.SetFocus(app.messageInput) } @@ -549,7 +550,6 @@ func (ml *messagesList) delete() { } ml.selectedMessageID = 0 - app.messageInput.replyMessageID = 0 ml.Highlight() if err := discordState.MessageRemove(app.guildsTree.selectedChannelID, msg.ID); err != nil { diff --git a/go.mod b/go.mod index ec7b432..6a385d4 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/diamondburned/ningen/v3 v3.0.1-0.20250703054403-e5dc4cf15e84 github.com/gdamore/tcell/v2 v2.8.1 github.com/gen2brain/beeep v0.11.1 + github.com/ncruces/zenity v0.10.14 github.com/sahilm/fuzzy v0.1.1 github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 github.com/spf13/cobra v1.9.1 @@ -21,7 +22,9 @@ require ( require ( al.essio.dev/pkg/shellescape v1.6.0 // indirect git.sr.ht/~jackmordaunt/go-toast v1.1.2 // indirect + github.com/akavel/rsrc v0.10.2 // indirect github.com/danieljoos/wincred v1.2.2 // indirect + github.com/dchest/jsmin v1.0.0 // indirect github.com/esiqveland/notify v0.13.3 // indirect github.com/gdamore/encoding v1.0.1 // indirect github.com/go-ole/go-ole v1.3.0 // indirect @@ -30,10 +33,12 @@ require ( github.com/gorilla/websocket v1.5.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackmordaunt/icns/v3 v3.0.1 // indirect + github.com/josephspurrier/goversioninfo v1.5.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/randall77/makefat v0.0.0-20210315173500-7ddd0e42c844 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/sergeymakinen/go-bmp v1.0.0 // indirect github.com/sergeymakinen/go-ico v1.0.0-beta.0 // indirect @@ -41,6 +46,7 @@ require ( github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect github.com/twmb/murmur3 v1.1.8 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect + golang.org/x/image v0.29.0 // indirect golang.org/x/sys v0.34.0 // indirect golang.org/x/term v0.33.0 // indirect golang.org/x/text v0.27.0 // indirect diff --git a/go.sum b/go.sum index 3b84f59..c52c88c 100644 --- a/go.sum +++ b/go.sum @@ -23,6 +23,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/akavel/rsrc v0.10.2 h1:Zxm8V5eI1hW4gGaYsJQUhxpjkENuG91ki8B4zCrvEsw= +github.com/akavel/rsrc v0.10.2/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/ayn2op/tview v0.0.0-20250618224732-91a1a2f06994 h1:heK43Ba0uvQPH2BgJVFiB2G8vIJk1XocvFYCPfOSNhU= @@ -38,14 +40,14 @@ github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dchest/jsmin v0.0.0-20220218165748-59f39799265f h1:OGqDDftRTwrvUoL6pOG7rYTmWsTCvyEWFsMjg+HcOaA= +github.com/dchest/jsmin v0.0.0-20220218165748-59f39799265f/go.mod h1:Dv9D0NUlAsaQcGQZa5kc5mqR9ua72SmA8VXi4cd+cBw= +github.com/dchest/jsmin v1.0.0 h1:Y2hWXmGZiRxtl+VcTksyucgTlYxnhPzTozCwx9gy9zI= +github.com/dchest/jsmin v1.0.0/go.mod h1:AVBIund7Mr7lKXT70hKT2YgL3XEXUaUk5iw9DZ8b0Uc= github.com/deckarep/gosx-notifier v0.0.0-20180201035817-e127226297fb h1:6S+TKObz6+Io2c8IOkcbK4Sz7nj6RpEVU7TkvmsZZcw= github.com/deckarep/gosx-notifier v0.0.0-20180201035817-e127226297fb/go.mod h1:wf3nKtOnQqCp7kp9xB7hHnNlZ6m3NoiOxjrB9hFRq4Y= -github.com/diamondburned/arikawa/v3 v3.5.1-0.20250702014048-91c175a8e0e4 h1:24TheqHAPtaJG0RFkGq9XugUYKwg5xkmuEUCCrUeQgs= -github.com/diamondburned/arikawa/v3 v3.5.1-0.20250702014048-91c175a8e0e4/go.mod h1:thocAM2X8lRDHuEZR5vWYaT4w+tb/vOKa1qm+r0gs5A= github.com/diamondburned/arikawa/v3 v3.5.1-0.20250703053218-19d9c3f2e011 h1:N8ylXHkkDXsbtsA/by/yZUDKmfWZJ1JjTXGpHmIiR9M= github.com/diamondburned/arikawa/v3 v3.5.1-0.20250703053218-19d9c3f2e011/go.mod h1:thocAM2X8lRDHuEZR5vWYaT4w+tb/vOKa1qm+r0gs5A= -github.com/diamondburned/ningen/v3 v3.0.1-0.20250607192146-d6b46a4689a5 h1:JSR20qwKLYVl3KKy6mUY7f8ziD2GtGAa3P9G2CyFgwk= -github.com/diamondburned/ningen/v3 v3.0.1-0.20250607192146-d6b46a4689a5/go.mod h1:UU1lud9g/GBl2+CZ8nPCe3Qk1U6fABEP1fk1sUzo7w0= github.com/diamondburned/ningen/v3 v3.0.1-0.20250703054403-e5dc4cf15e84 h1:O/6NA4fQimjVNuT5F02kodPT2cz9Ltq2U96vxKYL0oA= github.com/diamondburned/ningen/v3 v3.0.1-0.20250703054403-e5dc4cf15e84/go.mod h1:UU1lud9g/GBl2+CZ8nPCe3Qk1U6fABEP1fk1sUzo7w0= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -103,6 +105,10 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackmordaunt/icns/v3 v3.0.1 h1:xxot6aNuGrU+lNgxz5I5H0qSeCjNKp8uTXB1j8D4S3o= github.com/jackmordaunt/icns/v3 v3.0.1/go.mod h1:5sHL59nqTd2ynTnowxB/MDQFhKNqkK8X687uKNygaSQ= +github.com/josephspurrier/goversioninfo v1.4.1 h1:5LvrkP+n0tg91J9yTkoVnt/QgNnrI1t4uSsWjIonrqY= +github.com/josephspurrier/goversioninfo v1.4.1/go.mod h1:JWzv5rKQr+MmW+LvM412ToT/IkYDZjaclF2pKDss8IY= +github.com/josephspurrier/goversioninfo v1.5.0 h1:9TJtORoyf4YMoWSOo/cXFN9A/lB3PniJ91OxIH6e7Zg= +github.com/josephspurrier/goversioninfo v1.5.0/go.mod h1:6MoTvFZ6GKJkzcdLnU5T/RGYUbHQbKpYeNP0AgQLd2o= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -115,6 +121,8 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69 github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/ncruces/zenity v0.10.14 h1:OBFl7qfXcvsdo1NUEGxTlZvAakgWMqz9nG38TuiaGLI= +github.com/ncruces/zenity v0.10.14/go.mod h1:ZBW7uVe/Di3IcRYH0Br8X59pi+O6EPnNIOU66YHpOO4= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -122,6 +130,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/randall77/makefat v0.0.0-20210315173500-7ddd0e42c844 h1:GranzK4hv1/pqTIhMTXt2X8MmMOuH3hMeUR0o9SP5yc= +github.com/randall77/makefat v0.0.0-20210315173500-7ddd0e42c844/go.mod h1:T1TLSfyWVBRXVGzWd0o9BI4kfoO9InEgfQe4NV3mLz8= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= @@ -147,6 +157,7 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -165,6 +176,8 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -185,6 +198,10 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw= +golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM= +golang.org/x/image v0.29.0 h1:HcdsyR4Gsuys/Axh0rDEmlBmB68rW1U9BUdB3UVHsas= +golang.org/x/image v0.29.0/go.mod h1:RVJROnf3SLK8d26OW91j4FrIHGbsJ8QnbEocVTOWQDA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -266,8 +283,6 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= @@ -279,8 +294,6 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= -golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= -golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -295,8 +308,6 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/internal/config/config.toml b/internal/config/config.toml index 1ee2df7..bb20b39 100644 --- a/internal/config/config.toml +++ b/internal/config/config.toml @@ -88,12 +88,12 @@ yank_id = "Rune[i]" # Alt+Enter: Insert a new line to the current text. [keys.message_input] send = "Enter" -# Open message input in your editor. -editor = "Ctrl+E" # Remove existing text or cancel reply. cancel = "Esc" # Complete usernames when mentioning tab_complete = "Tab" +open_editor = "Ctrl+E" +open_file_picker = "Ctrl+\\" [keys.mentions_list] up = "Up" diff --git a/internal/config/keys.go b/internal/config/keys.go index 4981d3b..fe4c520 100644 --- a/internal/config/keys.go +++ b/internal/config/keys.go @@ -49,9 +49,11 @@ type ( MessageInputKeys struct { Send string `toml:"send"` - Editor string `toml:"editor"` Cancel string `toml:"cancel"` TabComplete string `toml:"tab_complete"` + + OpenEditor string `toml:"open_editor"` + OpenFilePicker string `toml:"open_file_picker"` } MentionsListKeys struct {