diff --git a/go.mod b/go.mod index 03ce490..25c7ae3 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/BurntSushi/toml v1.6.0 github.com/alecthomas/chroma/v2 v2.23.1 github.com/andybalholm/brotli v1.2.0 - github.com/ayn2op/clipboard v0.0.0-20260308080338-b25f12248108 + github.com/ayn2op/clipboard v0.0.0-20260308203959-c5ad7df3fc97 github.com/ayn2op/tview v0.0.0-20260304052427-7549865d186e github.com/deckarep/gosx-notifier v0.0.0-20180201035817-e127226297fb github.com/diamondburned/arikawa/v3 v3.6.1-0.20260308005009-475d37ffd5fa @@ -56,8 +56,8 @@ require ( golang.org/x/exp/shiny v0.0.0-20260218203240-3dfff04db8fa // indirect golang.org/x/image v0.36.0 // indirect golang.org/x/mobile v0.0.0-20260217195705-b56b3793a9c4 // indirect - golang.org/x/sys v0.41.0 // indirect + golang.org/x/sys v0.42.0 // indirect golang.org/x/term v0.40.0 // indirect golang.org/x/text v0.34.0 // indirect - golang.org/x/time v0.14.0 // indirect + golang.org/x/time v0.15.0 // indirect ) diff --git a/go.sum b/go.sum index 1dee1af..f650f9b 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ= github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= -github.com/ayn2op/clipboard v0.0.0-20260308080338-b25f12248108 h1:7iC49NDHu4nF6EqySoIntQ88ceHeMVM198wMBAOFDFU= -github.com/ayn2op/clipboard v0.0.0-20260308080338-b25f12248108/go.mod h1:3kFnpNCa3dF6WryzOMCDao7PfZ7DTCh+pievlfuwV80= +github.com/ayn2op/clipboard v0.0.0-20260308203959-c5ad7df3fc97 h1:WujETUV+v0DEJyZgjeLzQvihWyL80c0Tg4qf0dDo+Io= +github.com/ayn2op/clipboard v0.0.0-20260308203959-c5ad7df3fc97/go.mod h1:3kFnpNCa3dF6WryzOMCDao7PfZ7DTCh+pievlfuwV80= github.com/ayn2op/tview v0.0.0-20260304052427-7549865d186e h1:fc5qHUJV+XYlYabsJtWW/AwbGLFu6XMFTiHXDViUBeM= github.com/ayn2op/tview v0.0.0-20260304052427-7549865d186e/go.mod h1:lZ8RdOegQWBQafTOasGE7Ps1/Ymy4jmXoPt5vz2QsS0= github.com/danieljoos/wincred v1.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ= @@ -139,8 +139,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -153,8 +153,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= -golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= -golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/internal/clipboard/clipboard.go b/internal/clipboard/clipboard.go index 58b603a..9cfcb67 100644 --- a/internal/clipboard/clipboard.go +++ b/internal/clipboard/clipboard.go @@ -1,10 +1,10 @@ package clipboard -import designClipb "github.com/ayn2op/clipboard" +import "github.com/ayn2op/clipboard" -type Format = designClipb.Format +type Format = clipboard.Format const ( - FmtText Format = designClipb.FmtText - FmtImage = designClipb.FmtImage + FmtText Format = clipboard.FmtText + FmtImage = clipboard.FmtImage ) diff --git a/internal/clipboard/clipboard_default.go b/internal/clipboard/clipboard_default.go index 9d1ef78..bcada6f 100644 --- a/internal/clipboard/clipboard_default.go +++ b/internal/clipboard/clipboard_default.go @@ -1,11 +1,19 @@ -//go:build !linux +//go:build !linux && !freebsd package clipboard -import designClipb "github.com/ayn2op/clipboard" - -var ( - Init = designClipb.Init - Read = designClipb.Read - Write = designClipb.Write +import ( + "github.com/ayn2op/clipboard" ) + +func Init() error { + return clipboard.Init() +} + +func Read(t Format) ([]byte, error) { + return clipboard.Read(clipboard.Format(t)) +} + +func Write(t Format, buf []byte) error { + return clipboard.Write(clipboard.Format(t), buf) +} diff --git a/internal/clipboard/clipboard_linux.go b/internal/clipboard/clipboard_wayland.go similarity index 64% rename from internal/clipboard/clipboard_linux.go rename to internal/clipboard/clipboard_wayland.go index f7df7ae..3d11f15 100644 --- a/internal/clipboard/clipboard_linux.go +++ b/internal/clipboard/clipboard_wayland.go @@ -1,11 +1,10 @@ -//go:build linux +//go:build linux || freebsd package clipboard import ( "bytes" - designClipb "github.com/ayn2op/clipboard" - "log/slog" + "github.com/ayn2op/clipboard" "os" "os/exec" ) @@ -14,7 +13,7 @@ var wayland bool func Init() error { if _, ok := os.LookupEnv("WAYLAND_DISPLAY"); !ok { - return designClipb.Init() + return clipboard.Init() } if _, err := exec.LookPath("wl-copy"); err != nil { return err @@ -26,9 +25,9 @@ func Init() error { return nil } -func Read(t Format) []byte { +func Read(t Format) ([]byte, error) { if !wayland { - return designClipb.Read(designClipb.Format(t)) + return clipboard.Read(clipboard.Format(t)) } // -n: Don't print a newline at the end // -t type: MIME type specifier @@ -36,23 +35,19 @@ func Read(t Format) []byte { outBuffer := bytes.Buffer{} cmd.Stdout = &outBuffer if err := cmd.Run(); err != nil { - slog.Error("failed to read clipboard", "err", err) - return nil + return nil, err } - return outBuffer.Bytes() + return outBuffer.Bytes(), nil } -func Write(t Format, buf []byte) <-chan struct{} { +func Write(t Format, buf []byte) error { if !wayland { - return designClipb.Write(designClipb.Format(t), buf) + return clipboard.Write(clipboard.Format(t), buf) } // -t type: MIME type specifier cmd := exec.Command("wl-copy", "-t", formatToType(t)) cmd.Stdin = bytes.NewReader(buf) - if err := cmd.Run(); err != nil { - slog.Error("failed to write to clipboard", "err", err) - } - return nil + return cmd.Run() } func formatToType(t Format) string { diff --git a/internal/ui/chat/guilds_tree.go b/internal/ui/chat/guilds_tree.go index dc39ae8..5e61d4c 100644 --- a/internal/ui/chat/guilds_tree.go +++ b/internal/ui/chat/guilds_tree.go @@ -436,7 +436,11 @@ func (gt *guildsTree) yankID() { // Reference of a tree node in the guilds tree is its ID. // discord.Snowflake (discord.GuildID and discord.ChannelID) have the String method. if id, ok := node.GetReference().(fmt.Stringer); ok { - go clipboard.Write(clipboard.FmtText, []byte(id.String())) + go func() { + if err := clipboard.Write(clipboard.FmtText, []byte(id.String())); err != nil { + slog.Error("failed to copy node id", "err", err) + } + }() } } diff --git a/internal/ui/chat/message_input.go b/internal/ui/chat/message_input.go index c4973bd..6dc5b27 100644 --- a/internal/ui/chat/message_input.go +++ b/internal/ui/chat/message_input.go @@ -69,8 +69,19 @@ func newMessageInput(cfg *config.Config, chatView *View) *messageInput { mi. SetPlaceholder(tview.NewLine(tview.NewSegment("Select a channel to start chatting", tcell.StyleDefault.Dim(true)))). SetClipboard( - func(s string) { clipboard.Write(clipboard.FmtText, []byte(s)) }, - func() string { return string(clipboard.Read(clipboard.FmtText)) }, + func(s string) { + if err := clipboard.Write(clipboard.FmtText, []byte(s)); err != nil { + slog.Error("failed to write clipboard text", "err", err) + } + }, + func() string { + data, err := clipboard.Read(clipboard.FmtText) + if err != nil { + slog.Error("failed to read clipboard text", "err", err) + return "" + } + return string(data) + }, ). SetDisabled(true) @@ -187,7 +198,12 @@ func (mi *messageInput) HandleEvent(event tcell.Event) tview.Command { } func (mi *messageInput) paste() { - if data := clipboard.Read(clipboard.FmtImage); data != nil { + data, err := clipboard.Read(clipboard.FmtImage) + if err != nil { + slog.Error("failed to read clipboard image", "err", err) + return + } + if data != nil { name := "clipboard.png" mi.attach(name, bytes.NewReader(data)) } diff --git a/internal/ui/chat/messages_list.go b/internal/ui/chat/messages_list.go index 91e9ab3..aff5579 100644 --- a/internal/ui/chat/messages_list.go +++ b/internal/ui/chat/messages_list.go @@ -1022,7 +1022,11 @@ func (ml *messagesList) yankID() { return } - go clipboard.Write(clipboard.FmtText, []byte(msg.ID.String())) + go func() { + if err := clipboard.Write(clipboard.FmtText, []byte(msg.ID.String())); err != nil { + slog.Error("failed to copy message id", "err", err) + } + }() } func (ml *messagesList) yankContent() { @@ -1032,7 +1036,11 @@ func (ml *messagesList) yankContent() { return } - go clipboard.Write(clipboard.FmtText, []byte(msg.Content)) + go func() { + if err := clipboard.Write(clipboard.FmtText, []byte(msg.Content)); err != nil { + slog.Error("failed to copy message content", "err", err) + } + }() } func (ml *messagesList) yankURL() { @@ -1042,7 +1050,11 @@ func (ml *messagesList) yankURL() { return } - go clipboard.Write(clipboard.FmtText, []byte(msg.URL())) + go func() { + if err := clipboard.Write(clipboard.FmtText, []byte(msg.URL())); err != nil { + slog.Error("failed to copy message url", "err", err) + } + }() } func (ml *messagesList) open() { diff --git a/internal/ui/login/form.go b/internal/ui/login/form.go index 6d53203..d405851 100644 --- a/internal/ui/login/form.go +++ b/internal/ui/login/form.go @@ -64,7 +64,11 @@ func (f *Form) onError(err error) { AddButtons([]string{"Copy", "Close"}). SetDoneFunc(func(buttonIndex int, _ string) { if buttonIndex == 0 { - go clipboard.Write(clipboard.FmtText, []byte(message)) + go func() { + if err := clipboard.Write(clipboard.FmtText, []byte(message)); err != nil { + slog.Error("failed to copy error message", "err", err) + } + }() } else { f.RemoveLayer(errorLayerName) }