This commit is contained in:
2026-05-08 06:56:51 +01:00
parent 9593e7c041
commit 9bbefbcea8
7 changed files with 80 additions and 40 deletions
+5
View File
@@ -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)
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

+3 -1
View File
@@ -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")
+30 -6
View File
@@ -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)
+19 -13
View File
@@ -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
+21 -19
View File
@@ -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)
+1
View File
@@ -23,6 +23,7 @@ type lambdaConfig struct {
CVD color.CVD
Identicons bool
Debug bool
ShowPresenceUpdates bool
}
type mucUnit struct {