From 654ab8b618660767c557fedaa83fed0c0bab0246 Mon Sep 17 00:00:00 2001 From: sunglocto Date: Thu, 12 Mar 2026 16:09:22 +0000 Subject: [PATCH] add some icons and only store members by resource --- assets.go | 13 +++++++++++++ assets/client_icons/README | 1 + cache.go | 3 +++ failed_load.png | Bin 0 -> 5578 bytes gtk-helpers.go | 8 ++++---- gtk-message.go | 21 +++++++++++++++------ main.go | 20 +++++++++++++++----- please_wait.png | Bin 0 -> 5585 bytes xmpp-mentions.go | 1 + 9 files changed, 52 insertions(+), 15 deletions(-) create mode 100644 assets/client_icons/README create mode 100644 failed_load.png create mode 100644 please_wait.png diff --git a/assets.go b/assets.go index 87c25c2..a737c0f 100644 --- a/assets.go +++ b/assets.go @@ -11,6 +11,10 @@ import ( var defaultAvatarBytes []byte var defaultAvatarB64 string = base64.StdEncoding.EncodeToString(defaultAvatarBytes) +//go:embed failed_load.png +var failedBytes []byte +var failedB64 string = base64.StdEncoding.EncodeToString(failedBytes) + //go:embed assets/owner.png var ownerMedalBytes []byte var ownerMedalB64 string = base64.StdEncoding.EncodeToString(ownerMedalBytes) @@ -100,6 +104,15 @@ func init() { loader.Close() clientAssets["DefaultAvatar"] = gdk.NewTextureForPixbuf(loader.Pixbuf()) + + loader = gdkpixbuf.NewPixbufLoader() + + failedData, _ := base64.StdEncoding.DecodeString(failedB64) + loader.Write(failedData) + loader.Close() + + clientAssets["FailedAvatar"] = gdk.NewTextureForPixbuf(loader.Pixbuf()) + loader = gdkpixbuf.NewPixbufLoader() ownerMedalData, _ := base64.StdEncoding.DecodeString(ownerMedalB64) diff --git a/assets/client_icons/README b/assets/client_icons/README new file mode 100644 index 0000000..f92ca0a --- /dev/null +++ b/assets/client_icons/README @@ -0,0 +1 @@ +All client assets are owned by their respective owners diff --git a/cache.go b/cache.go index 337171a..267ca68 100644 --- a/cache.go +++ b/cache.go @@ -18,6 +18,9 @@ import ( // global or app-level map/cache var textureCache = make(map[string]gdk.Paintabler) +// Invalid images, if an image/avatar cannot be loaded on the system (e.g: incompatible format) it's put here +var invalidImages = make(map[string]bool) + func ensureCache() (string, error) { cachePath := configdir.LocalCache("lambda-im") err := configdir.MakePath(cachePath) // Ensure it exists. diff --git a/failed_load.png b/failed_load.png new file mode 100644 index 0000000000000000000000000000000000000000..291626c5acfdcec136495e0626bfe5204a858e1f GIT binary patch literal 5578 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 literal 0 HcmV?d00001 diff --git a/gtk-helpers.go b/gtk-helpers.go index dfb055e..f6b5e11 100644 --- a/gtk-helpers.go +++ b/gtk-helpers.go @@ -70,10 +70,10 @@ func switchToTab(jid string, w *gtk.Window) { var ocu OccupantID u.Get(&mu) u.Get(&ocu) - id := ocu.ID - if id == "" { - id = JidMustParse(u.From).Resource - } + //id := ocu.ID + //if id == "" { + id := JidMustParse(u.From).Resource + //} nick_label := gtk.NewLabel(JidMustParse(u.From).Resource) nick_label.SetEllipsize(pango.EllipsizeEnd) diff --git a/gtk-message.go b/gtk-message.go index a21a73c..e7b3d0d 100644 --- a/gtk-message.go +++ b/gtk-message.go @@ -151,10 +151,10 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter { ocu := OccupantID{} m.Get(&ocu) - id := ocu.ID - if id == "" { - id = JidMustParse(m.From).Resource - } + //id := ocu.ID + // if id == "" { + id := JidMustParse(m.From).Resource + // } authorBox := gtk.NewBox(gtk.OrientationHorizontal, 10) @@ -265,9 +265,10 @@ func getVAdjustment(scrolledWindow *gtk.ScrolledWindow) *gtk.Adjustment { } func getAvatar(j, hash string) *gtk.Image { // TODO: This function probably shouldn't be here, and should probably be in xmpp-helpers or somewhere similar. + oghash := hash p, err := ensureCache() if err != nil { - return gtk.NewImageFromPaintable(clientAssets["DefaultAvatar"]) + return gtk.NewImageFromPaintable(clientAssets["FailedAvatar"]) } if hash == "" { @@ -275,6 +276,12 @@ func getAvatar(j, hash string) *gtk.Image { // TODO: This function probably shou return gtk.NewImageFromPaintable(clientAssets["DefaultAvatar"]) } + _, ok := invalidImages[hash] + if ok { + fmt.Println("Image is invalid") + return gtk.NewImageFromPaintable(clientAssets["FailedAvatar"]) + } + hash = filepath.Join(p, sanitizefilename.Sanitize(hash)) _, err = os.ReadFile(hash) @@ -309,7 +316,9 @@ func getAvatar(j, hash string) *gtk.Image { // TODO: This function probably shou base64_data := card.Photo.Binval if card.Photo.Binval == "" || ((card.Photo.Type == "image/svg+xml" || card.Photo.Type == "image/webp") && (runtime.GOOS == "windows" || runtime.GOOS == "netbsd")) { - return gtk.NewImageFromPaintable(clientAssets["DefaultAvatar"]) + fmt.Println("Blocking image") + invalidImages[oghash] = true + return gtk.NewImageFromPaintable(clientAssets["FailedAvatar"]) } data, err := base64.StdEncoding.DecodeString(base64_data) diff --git a/main.go b/main.go index 2e5e83b..2dc6d14 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "strings" "os" "sync" @@ -121,7 +122,7 @@ func main() { Jid: loadedConfig.Username + "/" + loadedConfig.Resource, Credential: xmpp.Password(loadedConfig.Password), Insecure: loadedConfig.Insecure, - // StreamLogger: os.Stdout, + StreamLogger: os.Stdout, StreamManagementEnable: true, } router := xmpp.NewRouter() @@ -282,10 +283,10 @@ func main() { if ok { // This is a presence stanza from a user in a MUC presence.Get(&ocu) - id := ocu.ID - if id == "" { - id = JidMustParse(presence.From).Resource - } + // id := ocu.ID + // if id == "" { + id := JidMustParse(presence.From).Resource + // } from, _ := stanza.NewJid(presence.From) muc := from.Bare() _, ok = mucmembers.Load(muc) @@ -868,6 +869,15 @@ func activate(app *gtk.Application) { exts = append(exts, new_oob) } + if strings.Contains(t, "@everyone") { + new_mention := new(Mention) + new_mention.Mentions = "urn:xmpp:mentions:0#channel" + exts = append(exts, new_mention) + } else if strings.Contains(t, "@here") { + new_attention := new(Attention) + exts = append(exts, new_attention) + } + err := sendMessage(client, current, message_type, t, "", "", exts) if err != nil { panic(err) // TODO: Show error message via GTK diff --git a/please_wait.png b/please_wait.png new file mode 100644 index 0000000000000000000000000000000000000000..0918883a0ab7b282e112397cc2436d02ccdab7d5 GIT binary patch literal 5585 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 literal 0 HcmV?d00001 diff --git a/xmpp-mentions.go b/xmpp-mentions.go index 11b4b6e..7344a18 100644 --- a/xmpp-mentions.go +++ b/xmpp-mentions.go @@ -16,6 +16,7 @@ type Mention struct { Begin int `xml:"begin,attr,omitempty"` End int `xml:"end,attr,omitempty"` OccupantID string `xml:"occupantid,attr,omitempty"` + JID string `xml:"ji,attr,omitempty"` } func init() {