From e8b5f0b3c46d1620d1866f9b800098b1759742ab Mon Sep 17 00:00:00 2001 From: Will Norris Date: Mon, 31 Mar 2025 17:37:21 -0700 Subject: [PATCH] client/systray: use ico image format for windows Add the golang-image-ico package, which is an incredibly small package to handle the ICO container format with PNG inside. Some profile photos look quite pixelated when displayed at this size, but it's better than nothing, and any Windows support is just a bonus anyway. Updates #1708 Change-Id: Ia101a4a3005adb9118051b3416f5a64a4a45987d Signed-off-by: Will Norris --- client/systray/logo.go | 10 +++++++++- client/systray/systray.go | 17 +++++++++++++++++ go.mod | 5 +++-- go.sum | 10 ++++++---- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/client/systray/logo.go b/client/systray/logo.go index 857a8a937..3467d1b74 100644 --- a/client/systray/logo.go +++ b/client/systray/logo.go @@ -11,10 +11,12 @@ import ( "image" "image/color" "image/png" + "runtime" "sync" "time" "fyne.io/systray" + ico "github.com/Kodeworks/golang-image-ico" "github.com/fogleman/gg" ) @@ -251,7 +253,13 @@ func (logo tsLogo) renderWithBorder(borderUnits int) *bytes.Buffer { } b := bytes.NewBuffer(nil) - png.Encode(b, dc.Image()) + + // Encode as ICO format on Windows, PNG on all other platforms. + if runtime.GOOS == "windows" { + _ = ico.Encode(b, dc.Image()) + } else { + _ = png.Encode(b, dc.Image()) + } return b } diff --git a/client/systray/systray.go b/client/systray/systray.go index b5bde551c..781a65bb8 100644 --- a/client/systray/systray.go +++ b/client/systray/systray.go @@ -7,9 +7,11 @@ package systray import ( + "bytes" "context" "errors" "fmt" + "image" "io" "log" "net/http" @@ -23,6 +25,7 @@ import ( "time" "fyne.io/systray" + ico "github.com/Kodeworks/golang-image-ico" "github.com/atotto/clipboard" dbus "github.com/godbus/dbus/v5" "github.com/toqueteos/webbrowser" @@ -330,6 +333,20 @@ func setRemoteIcon(menu *systray.MenuItem, urlStr string) { resp, err := http.Get(urlStr) if err == nil && resp.StatusCode == http.StatusOK { b, _ = io.ReadAll(resp.Body) + + // Convert image to ICO format on Windows + if runtime.GOOS == "windows" { + im, _, err := image.Decode(bytes.NewReader(b)) + if err != nil { + return + } + buf := bytes.NewBuffer(nil) + if err := ico.Encode(buf, im); err != nil { + return + } + b = buf.Bytes() + } + httpCache[urlStr] = b resp.Body.Close() } diff --git a/go.mod b/go.mod index a566c941f..7be824165 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,8 @@ go 1.24.0 require ( filippo.io/mkcert v1.4.4 - fyne.io/systray v1.11.0 + fyne.io/systray v1.11.1-0.20250317195939-bcf6eed85e7a + github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9 github.com/akutz/memconn v0.1.0 github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa github.com/andybalholm/brotli v1.1.0 @@ -100,7 +101,7 @@ require ( golang.org/x/net v0.36.0 golang.org/x/oauth2 v0.26.0 golang.org/x/sync v0.11.0 - golang.org/x/sys v0.30.0 + golang.org/x/sys v0.31.0 golang.org/x/term v0.29.0 golang.org/x/time v0.10.0 golang.org/x/tools v0.30.0 diff --git a/go.sum b/go.sum index 528e48c16..fffa17209 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= filippo.io/mkcert v1.4.4 h1:8eVbbwfVlaqUM7OwuftKc2nuYOoTDQWqsoXmzoXZdbc= filippo.io/mkcert v1.4.4/go.mod h1:VyvOchVuAye3BoUsPUOOofKygVwLV2KQMVFJNRq+1dA= -fyne.io/systray v1.11.0 h1:D9HISlxSkx+jHSniMBR6fCFOUjk1x/OOOJLa9lJYAKg= -fyne.io/systray v1.11.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs= +fyne.io/systray v1.11.1-0.20250317195939-bcf6eed85e7a h1:I8mEKo5sawHu8CqYf3FSjIl9b3puXasFVn2D/hrCneY= +fyne.io/systray v1.11.1-0.20250317195939-bcf6eed85e7a/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs= github.com/4meepo/tagalign v1.3.3 h1:ZsOxcwGD/jP4U/aw7qeWu58i7dwYemfy5Y+IF1ACoNw= github.com/4meepo/tagalign v1.3.3/go.mod h1:Q9c1rYMZJc9dPRkbQPpcBNCLEmY2njbAsXhQOZFE2dE= github.com/Abirdcfly/dupword v0.0.14 h1:3U4ulkc8EUo+CaT105/GJ1BQwtgyj6+VaBVbAX11Ba8= @@ -67,6 +67,8 @@ github.com/Djarvur/go-err113 v0.1.0 h1:uCRZZOdMQ0TZPHYTdYpoC0bLYJKPEHPUJ8MeAa51l github.com/Djarvur/go-err113 v0.1.0/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0 h1:sATXp1x6/axKxz2Gjxv8MALP0bXaNRfQinEwyfMcx8c= github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0/go.mod h1:Nl76DrGNJTA1KJ0LePKBw/vznBX1EHbAZX8mwjR82nI= +github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9 h1:1ltqoej5GtaWF8jaiA49HwsZD459jqm9YFz9ZtMFpQA= +github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= @@ -1218,8 +1220,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=