Files
lambda/gtk-message.go

208 lines
4.5 KiB
Go
Raw Normal View History

2026-01-29 21:35:36 +00:00
package main
// This file contains the function that generates message widgets depending on message stanza
import (
2026-01-30 13:29:53 +00:00
"context"
2026-01-30 15:56:58 +00:00
"encoding/base64"
2026-01-29 21:35:36 +00:00
"fmt"
"github.com/diamondburned/gotk4/pkg/gtk/v4"
"github.com/google/uuid"
2026-01-30 13:29:53 +00:00
"github.com/jacoblockett/sanitizefilename"
2026-01-30 15:56:58 +00:00
"github.com/jasonlovesdoggo/gopen"
"gosrc.io/xmpp/stanza"
"mellium.im/xmpp/jid"
"os"
"path/filepath"
2026-01-29 21:35:36 +00:00
)
func generateMessageWidget(p stanza.Packet) gtk.Widgetter {
m, ok := p.(stanza.Message)
if !ok {
return gtk.NewLabel("Unsupported message.")
}
sid := StanzaID{}
m.Get(&sid)
mainBox := gtk.NewBox(gtk.OrientationVertical, 0)
gesture := gtk.NewGestureClick()
gesture.SetButton(3) // Right click
vis := false
reactions := gtk.NewBox(gtk.OrientationHorizontal, 0)
reactions.SetVisible(false)
2026-01-30 15:56:58 +00:00
reaction := []string{"👍", "👎", "♥️", "🤣", "😭"}
2026-01-29 21:35:36 +00:00
for _, v := range reaction {
like := gtk.NewButton()
like.SetLabel(v)
like.SetHExpand(true)
like.ConnectClicked(func() {
fmt.Println("licked")
client.SendRaw(fmt.Sprintf(`
<message from='%s' to='%s' id='%s' type='%s'>
<reactions id='%s' xmlns='urn:xmpp:reactions:0'>
<reaction>%s</reaction>
</reactions>
</message>
`, m.To, jid.MustParse(m.From).Bare().String(), uuid.New().String(), m.Type, sid.ID, v))
})
reactions.Append(like)
}
gesture.Connect("pressed", func(n_press, x, y int) {
if !vis {
vis = true
reactions.SetVisible(true)
} else {
vis = false
reactions.SetVisible(false)
}
})
mainBox.AddController(gesture)
reply := Reply{}
ok = m.Get(&reply)
if ok {
replyBox := gtk.NewBox(gtk.OrientationHorizontal, 0)
replyBox.Append(gtk.NewLabel("↱ " + jid.MustParse(reply.To).Resourcepart()))
mainBox.Append(replyBox)
}
2026-01-30 13:29:53 +00:00
ocu := OccupantID{}
2026-01-30 19:08:18 +00:00
2026-01-30 13:29:53 +00:00
m.Get(&ocu)
2026-01-29 21:35:36 +00:00
authorBox := gtk.NewBox(gtk.OrientationHorizontal, 10)
contentBox := gtk.NewBox(gtk.OrientationHorizontal, 0)
2026-01-30 13:29:53 +00:00
// im := newImageFromPath("debug.png")
2026-01-29 21:35:36 +00:00
2026-01-30 13:29:53 +00:00
// authorBox.Append(im)
2026-01-30 19:08:18 +00:00
mo, _ := mucmembers.Load(jid.MustParse(m.From).Bare().String())
mm := mo.(mucUnit)
mmm := mm.Members
mmmm, ok := mmm.Load(ocu.ID)
if ok {
pres := mmmm.(stanza.Presence)
var vu VCardUpdate
pres.Get(&vu)
if vu.Photo != "" {
im := getAvatar(m.From, vu.Photo)
im.SetPixelSize(40)
im.AddCSSClass("author_img")
authorBox.Append(im)
} else {
im := newImageFromPath("debug.png")
im.SetPixelSize(40)
im.AddCSSClass("author_img")
}
} else {
im := newImageFromPath("debug.png")
im.SetPixelSize(40)
im.AddCSSClass("author_img")
}
2026-01-29 21:35:36 +00:00
al := gtk.NewLabel(jid.MustParse(m.From).Resourcepart())
al.AddCSSClass("author")
authorBox.Append(al)
mlabel := gtk.NewLabel(m.Body)
// mlabel.SetMarkup(convertXEPToPango(m.Body))
mlabel.SetWrap(true)
mlabel.SetSelectable(true)
mlabel.SetHAlign(gtk.AlignFill)
contentBox.Append(mlabel)
mainBox.Append(authorBox)
mainBox.Append(contentBox)
mainBox.Append(reactions)
oob := stanza.OOB{}
ok = m.Get(&oob)
if ok {
2026-01-30 15:56:58 +00:00
// media := newPictureFromWeb(oob.URL)
2026-01-29 21:35:36 +00:00
// media.SetCanShrink(false)
// mainBox.Append(media)
// media.AddCSSClass("chat_image")
mbtn := gtk.NewButtonWithLabel("🖼️")
2026-01-30 10:40:38 +00:00
// mbtn.SetChild(newImageFromWeb(oob.URL))
2026-01-30 15:56:58 +00:00
mbtn.ConnectClicked(func() {
2026-01-29 21:35:36 +00:00
gopen.Open(oob.URL)
})
authorBox.Append(mbtn)
}
return mainBox
}
func getVAdjustment(scrolledWindow *gtk.ScrolledWindow) *gtk.Adjustment {
val := scrolledWindow.ObjectProperty("vadjustment").(*gtk.Adjustment)
return val
}
2026-01-30 13:29:53 +00:00
2026-01-30 15:56:58 +00:00
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.
p, err := ensureCache()
if err != nil {
return newImageFromPath("debug.png")
}
2026-01-30 19:08:18 +00:00
if hash == "" {
fmt.Println("Hash is nil!")
return newImageFromPath("debug.png")
}
2026-01-30 15:56:58 +00:00
hash = filepath.Join(p, sanitizefilename.Sanitize(hash))
2026-01-30 13:29:53 +00:00
2026-01-30 15:56:58 +00:00
_, err = os.ReadFile(hash)
2026-01-30 13:29:53 +00:00
if err == nil {
return newImageFromPath(hash)
}
iqResp, err := stanza.NewIQ(stanza.Attrs{
Type: "get",
From: clientroot.Session.BindJid,
2026-01-30 15:56:58 +00:00
To: j,
Id: "vc2",
Lang: "en",
2026-01-30 13:29:53 +00:00
})
if err != nil {
panic(err)
}
iqResp.Payload = &VCard{}
ctx := context.TODO()
mychan, err := client.SendIQ(ctx, iqResp)
if err != nil {
panic(err)
}
2026-01-30 15:56:58 +00:00
result := <-mychan
2026-01-30 13:29:53 +00:00
card, ok := result.Payload.(*VCard)
if !ok {
return newImageFromPath("debug.png")
}
base64_data := card.Photo.Binval
if card.Photo.Binval == "" {
return newImageFromPath("debug.png")
}
data, err := base64.StdEncoding.DecodeString(base64_data)
if err != nil {
panic(err)
}
err = os.WriteFile(hash, data, 0644)
if err != nil {
panic(err)
}
return newImageFromPath(hash)
2026-01-30 15:56:58 +00:00
}