diff --git a/assets.go b/assets.go index 0a52522..5ed90c0 100644 --- a/assets.go +++ b/assets.go @@ -140,6 +140,10 @@ var moderateBytes []byte //go:embed assets/jabber.png var jabberBytes []byte + +//go:embed assets/fail.png +var failBytes []byte + func loadAsset(key string, data []byte) { loader := gdkpixbuf.NewPixbufLoader() loader.Write(data) @@ -193,6 +197,7 @@ func init() { "muc_temporary": mucTemporaryBytes, "moderate": moderateBytes, "jabber": jabberBytes, + "fail": failBytes, } { loadAsset(key, data) } diff --git a/assets/fail.png b/assets/fail.png new file mode 100644 index 0000000..06b4d7a Binary files /dev/null and b/assets/fail.png differ diff --git a/cache.go b/cache.go index de20d70..eb52a02 100644 --- a/cache.go +++ b/cache.go @@ -21,7 +21,9 @@ import ( var textureCache sync.Map // 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) +// var invalidImages = make(map[string]bool) + +var invalidImages sync.Map func ensureCache() (string, error) { cachePath := configdir.LocalCache("lambda-im") diff --git a/gtk-helpers.go b/gtk-helpers.go index 806d62e..505071b 100644 --- a/gtk-helpers.go +++ b/gtk-helpers.go @@ -16,9 +16,13 @@ import ( "image" "image/png" xmpp_color "mellium.im/xmpp/color" + "image/color" "strconv" ) +func init() { +} + func scrollToBottomAfterUpdate(scrolledWindow *gtk.ScrolledWindow) { glib.IdleAdd(func() bool { vAdj := scrolledWindow.VAdjustment() @@ -63,10 +67,26 @@ func switchToTab(jid string, w *gtk.Window) { if typed_tab.isMuc { m, ok := mucmembers.Load(jid) if !ok { + box := gtk.NewBox(gtk.OrientationVertical, 10) + failed_icon := gtk.NewImageFromPaintable(clientAssets["fail"]) + failed_icon.SetPixelSize(100) + box.Append(failed_icon) + label := gtk.NewLabel("There was an error loading the members of this room. Maybe the MUC does not give user presence, it does not exist, you have been banned from it, or you have to fill a CAPTCHA to access it. Try joining the room again or check if the room exists.") + label.SetWrap(true) + box.Append(label) + memberList.SetChild(box) return } ma, ok := m.(mucUnit) if !ok { + box := gtk.NewBox(gtk.OrientationVertical, 10) + failed_icon := gtk.NewImageFromPaintable(clientAssets["fail"]) + failed_icon.SetPixelSize(100) + box.Append(failed_icon) + label := gtk.NewLabel("There was an error loading the members of this room. Maybe the MUC does not give user presence, it does not exist, you have been banned from it, or you have to fill a CAPTCHA to access it. Try joining the room again or check if the room exists.") + label.SetWrap(true) + box.Append(label) + memberList.SetChild(box) return } mm := ma.Members @@ -155,7 +175,7 @@ func switchToTab(jid string, w *gtk.Window) { medal.SetHExpand(true) userbox.Append(medal) - default_av := createIdenticon(u.From) + default_av := createIdenticon(u.From, false) userbox.Prepend(default_av) var vcu VCardUpdate ok = u.Get(&vcu) @@ -461,13 +481,13 @@ func switchToTab(jid string, w *gtk.Window) { im.AddCSSClass("author_img") profile_box.Prepend(im) } else { - im := createIdenticon(u.From) + im := createIdenticon(u.From, false) im.SetPixelSize(80) im.AddCSSClass("author_img") profile_box.Prepend(im) } } else { - im := createIdenticon(u.From) + im := createIdenticon(u.From, false) im.SetPixelSize(80) im.AddCSSClass("author_img") profile_box.Prepend(im) @@ -529,14 +549,18 @@ func showErrorDialog(err error) { err_win.Present() } -func createIdenticon(word string) *gtk.Image { // This function generates an identicon - if !loadedConfig.Identicons { +func createIdenticon(word string, always_create bool) *gtk.Image { // This function generates an identicon + if !loadedConfig.Identicons && !always_create { i := gtk.NewImageFromPaintable(clientAssets["DefaultAvatar"]) i.AddCSSClass(loadedConfig.CVD.String() + "_CVD") return i } - gen, _ := identicon.New("github", 5, 3) + identicon.SetBackgroundColorFunction(func([]byte, color.Color) color.Color { + return color.Transparent + }) + + gen, _ := identicon.New("", 5, 3) ii, _ := gen.Draw(word) im := ii.Image(250) diff --git a/gtk-message.go b/gtk-message.go index a1a9439..7b0dcb0 100644 --- a/gtk-message.go +++ b/gtk-message.go @@ -171,7 +171,7 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter { pres := mmmm.(stanza.Presence) var vu VCardUpdate pres.Get(&vu) - im := createIdenticon(m.From) + im := createIdenticon(m.From, false) im.SetPixelSize(40) im.AddCSSClass("author_img") authorBox.Append(im) @@ -188,7 +188,7 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter { } } else { - im := createIdenticon(m.From) + im := createIdenticon(m.From, false) im.SetPixelSize(40) im.AddCSSClass("author_img") authorBox.Append(im) @@ -199,6 +199,12 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter { authorBox.Append(al) + if m.Thread != "" { + im := createIdenticon(m.Thread, true) + im.SetPixelSize(10) + authorBox.Append(im) + } + wxdc := XDCEl{} ok = m.Get(&wxdc) if ok { @@ -288,16 +294,16 @@ func getAvatar(j, hash string) *gtk.Image { // TODO: This function probably shou oghash := hash p, err := ensureCache() if err != nil { - return createIdenticon(j) + return createIdenticon(j, false) } if hash == "" { - return createIdenticon(j) + return createIdenticon(j, false) } - _, ok := invalidImages[hash] + _, ok := invalidImages.Load(hash) if ok { - return createIdenticon(j) + return createIdenticon(j, false) } hash = filepath.Join(p, hash) @@ -306,8 +312,8 @@ func getAvatar(j, hash string) *gtk.Image { // TODO: This function probably shou if err == nil { i, err := newImageFromPath(hash) if err != nil { - invalidImages[oghash] = true - return createIdenticon(j) + invalidImages.Store(oghash, true) + return createIdenticon(j, false) } i.AddCSSClass(loadedConfig.CVD.String() + "_CVD") return i @@ -335,14 +341,14 @@ func getAvatar(j, hash string) *gtk.Image { // TODO: This function probably shou result := <-mychan card, ok := result.Payload.(*VCard) if !ok { - return createIdenticon(j) + return createIdenticon(j, false) } 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")) { fmt.Println("Blocking image") - invalidImages[oghash] = true - return createIdenticon(j) + invalidImages.Store(oghash, true) + return createIdenticon(j, false) } data, err := base64.StdEncoding.DecodeString(base64_data) @@ -357,8 +363,8 @@ func getAvatar(j, hash string) *gtk.Image { // TODO: This function probably shou i, err := newImageFromPath(hash) if err != nil { - invalidImages[oghash] = true - return createIdenticon(j) + invalidImages.Store(oghash, true) + return createIdenticon(j, false) } i.AddCSSClass(loadedConfig.CVD.String() + "_CVD") return i diff --git a/main.go b/main.go index 572cf41..842b879 100644 --- a/main.go +++ b/main.go @@ -346,7 +346,7 @@ func main() { if presence.Type != "unavailable" { _, ok := typed_unit.Members.Load(id) - if !ok { + if !ok && loadedConfig.ShowPresenceUpdates { glib.IdleAdd(func() { b := gtk.NewBox(gtk.OrientationVertical, 0) ba, ok := generatePresenceWidget(p).(*gtk.Box) @@ -370,25 +370,27 @@ func main() { typed_unit.Members.Store(id, presence) } else { typed_unit.Members.Delete(id) - glib.IdleAdd(func() { - b := gtk.NewBox(gtk.OrientationVertical, 0) - ba, ok := generatePresenceWidget(p).(*gtk.Box) - if ok { - b = ba - } - - tab, ok := tabs.Load(muc) - typed_tab := tab.(*chatTab) - - if ok { - typed_tab.msgs.Append(b) - if current == muc { - scrollToBottomAfterUpdate(scroller) + if loadedConfig.ShowPresenceUpdates { + glib.IdleAdd(func() { + b := gtk.NewBox(gtk.OrientationVertical, 0) + ba, ok := generatePresenceWidget(p).(*gtk.Box) + if ok { + b = ba } - } else { - fmt.Println("Got message when the tab does not exist!") - } - }) + + tab, ok := tabs.Load(muc) + typed_tab := tab.(*chatTab) + + if ok { + typed_tab.msgs.Append(b) + if current == muc { + scrollToBottomAfterUpdate(scroller) + } + } else { + fmt.Println("Got message when the tab does not exist!") + } + }) + } } mucmembers.Store(muc, typed_unit) @@ -510,7 +512,7 @@ func main() { jid := v.Jid if name == "" { - name = jid + name = jid } createTab(jid, false, name) diff --git a/types.go b/types.go index f38ba64..521232c 100644 --- a/types.go +++ b/types.go @@ -23,6 +23,7 @@ type lambdaConfig struct { CVD color.CVD Identicons bool Debug bool + ShowPresenceUpdates bool } type mucUnit struct {