format + allow closing

This commit is contained in:
2026-05-09 07:33:47 +01:00
parent 9bbefbcea8
commit 39cdd5e6c1
5 changed files with 112 additions and 54 deletions
-1
View File
@@ -140,7 +140,6 @@ var moderateBytes []byte
//go:embed assets/jabber.png
var jabberBytes []byte
//go:embed assets/fail.png
var failBytes []byte
+32 -3
View File
@@ -14,9 +14,9 @@ import (
"github.com/rrivera/identicon"
"gosrc.io/xmpp/stanza"
"image"
"image/color"
"image/png"
xmpp_color "mellium.im/xmpp/color"
"image/color"
"strconv"
)
@@ -54,6 +54,34 @@ func createTab(jid string, isMuc bool, name string) bool {
return false
}
func removeTab(jid string, w *gtk.Window) {
t, ok := tabs.Load(jid)
if ok {
tab := t.(*chatTab)
tab.msgs.RemoveAll()
if tab.isMuc {
client.SendRaw(fmt.Sprintf(`
<presence from='%s' to='%s' type='unavailable'>
<x xmlns='http://jabber.org/protocol/muc'/>
</presence>
`, clientroot.Session.BindJid, jid+"/"+tab.current_nick))
}
tabs.Delete(jid)
mucmembers.Delete(jid)
userdevices.Delete(jid)
if current == jid {
current = ""
scroller.SetChild(empty_dialog)
typingStatus.SetText("")
memberList.SetChild(gtk.NewLabel(""))
}
mucmembers.Delete(jid)
}
}
func switchToTab(jid string, w *gtk.Window) {
current = jid
tab, ok := tabs.Load(current)
@@ -160,7 +188,6 @@ func switchToTab(jid string, w *gtk.Window) {
}
}
status := gtk.NewImageFromPaintable(clientAssets["status_"+string(u.Show)])
status.SetTooltipText(string(u.Show))
@@ -521,6 +548,7 @@ func switchToTab(jid string, w *gtk.Window) {
gen.Prepend(muci)
muc_name := gtk.NewLabel(typed_tab.name)
muc_name.AddCSSClass("author")
muc_name.SetWrap(true)
gen.Prepend(muc_name)
memberList.SetChild(gen)
} else {
@@ -529,7 +557,7 @@ func switchToTab(jid string, w *gtk.Window) {
}
func showErrorDialog(err error) {
func showErrorDialog(err error, w *gtk.Window) {
err_win := gtk.NewWindow()
err_win.SetTitle(loadedLocale["error"])
err_win.SetDefaultSize(400, 200)
@@ -546,6 +574,7 @@ func showErrorDialog(err error) {
})
box.Append(close_btn)
err_win.SetChild(box)
err_win.SetTransientFor(w)
err_win.Present()
}
+28 -31
View File
@@ -92,46 +92,45 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter {
popover.SetParent(mainBox)
popover.SetHasArrow(false)
gesture.Connect("pressed", func(n_press, x, y int) {
rc_box := gtk.NewBox(gtk.OrientationVertical, 0)
rc_box := gtk.NewBox(gtk.OrientationVertical, 0)
reactions := gtk.NewBox(gtk.OrientationHorizontal, 0)
reaction := []string{"👍", "👎", "♥️", "🤣", "💀"}
for _, v := range reaction {
like := gtk.NewButton()
like.SetLabel(v)
like.SetHExpand(true)
like.ConnectClicked(func() {
fmt.Println("licked") // TODO: Implement proper support for reactions via extension
client.SendRaw(fmt.Sprintf(`
reactions := gtk.NewBox(gtk.OrientationHorizontal, 0)
reaction := []string{"👍", "👎", "♥️", "🤣", "💀"}
for _, v := range reaction {
like := gtk.NewButton()
like.SetLabel(v)
like.SetHExpand(true)
like.ConnectClicked(func() {
fmt.Println("licked") // TODO: Implement proper support for reactions via extension
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)
}
rc_box.Append(reactions)
quote := gtk.NewButtonWithLabel("Quote")
quote.ConnectClicked(func() {
lines := strings.Split(m.Body, "\n")
for i, line := range lines {
quoteline := "> " + line
lines[i] = quoteline
})
reactions.Append(like)
}
newstr := strings.Join(lines, "\n") + "\n\n"
rc_box.Append(reactions)
message_en.SetText(newstr)
})
rc_box.Append(quote)
quote := gtk.NewButtonWithLabel("Quote")
quote.ConnectClicked(func() {
lines := strings.Split(m.Body, "\n")
for i, line := range lines {
quoteline := "> " + line
lines[i] = quoteline
}
popover.SetChild(rc_box)
newstr := strings.Join(lines, "\n") + "\n\n"
message_en.SetText(newstr)
})
rc_box.Append(quote)
popover.SetChild(rc_box)
rect := gdk.NewRectangle(x, y, 1, 1)
popover.SetPointingTo(&rect)
popover.Popup()
@@ -233,7 +232,6 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter {
mainBox.Append(authorBox)
mainBox.Append(contentBox)
oob := stanza.OOB{}
ok = m.Get(&oob)
if ok {
@@ -315,7 +313,7 @@ func getAvatar(j, hash string) *gtk.Image { // TODO: This function probably shou
invalidImages.Store(oghash, true)
return createIdenticon(j, false)
}
i.AddCSSClass(loadedConfig.CVD.String() + "_CVD")
// i.AddCSSClass(loadedConfig.CVD.String() + "_CVD")
return i
}
@@ -346,7 +344,6 @@ 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")) {
fmt.Println("Blocking image")
invalidImages.Store(oghash, true)
return createIdenticon(j, false)
}
+38 -6
View File
@@ -325,6 +325,7 @@ func main() {
ok = presence.Get(&mu)
if ok { // This is a presence stanza from a user in a MUC
presence.Get(&ocu)
// id := ocu.ID
// if id == "" {
@@ -333,7 +334,7 @@ func main() {
from, _ := stanza.NewJid(presence.From)
muc := from.Bare()
_, ok = mucmembers.Load(muc)
if !ok {
if !ok && presence.Type != "unavailable" {
mucmembers.Store(muc, mucUnit{})
}
@@ -344,6 +345,14 @@ func main() {
typed_unit := unit.(mucUnit)
if mu.MucUserItem.JID == clientroot.Session.BindJid {
tab, ok := tabs.Load(muc)
if ok {
typed_tab := tab.(*chatTab)
typed_tab.current_nick = id
}
}
if presence.Type != "unavailable" {
_, ok := typed_unit.Members.Load(id)
if !ok && loadedConfig.ShowPresenceUpdates {
@@ -408,7 +417,7 @@ func main() {
})
if err != nil {
showErrorDialog(err)
showErrorDialog(err, &window.Window)
panic(err)
}
client = c
@@ -524,6 +533,13 @@ func main() {
gesture1.Connect("pressed", func() {
switchToTab(jid, &window.Window)
})
gesture2 := gtk.NewGestureClick()
gesture2.SetButton(3)
gesture2.Connect("pressed", func() {
removeTab(jid, &window.Window)
box.SetVisible(false)
})
box.Append(b)
go func() {
new_im := getAvatar(jid, jid) // TODO: Use PEP avatar and do not use JID as hash
@@ -604,6 +620,13 @@ func main() {
gesture1.Connect("pressed", func() {
switchToTab(jid, &window.Window)
})
gesture2 := gtk.NewGestureClick()
gesture2.SetButton(3)
gesture2.Connect("pressed", func() {
removeTab(jid, &window.Window)
box.SetVisible(false)
})
box.Append(b)
go func() {
new_im := getAvatar(jid, jid)
@@ -614,6 +637,7 @@ func main() {
}()
box.AddController(gesture1)
box.AddController(gesture2)
menu.Append(box)
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
})
@@ -840,7 +864,7 @@ func activate(app *gtk.Application) {
jm := func(n string, pw string) {
err := joinMuc(client, clientroot.Session.BindJid, t, nick_entry.Text(), pw)
if err != nil {
showErrorDialog(err)
showErrorDialog(err, win)
return
}
@@ -861,7 +885,15 @@ func activate(app *gtk.Application) {
switchToTab(t, &window.Window)
})
gesture2 := gtk.NewGestureClick()
gesture2.SetButton(3)
gesture2.Connect("pressed", func() {
removeTab(t, &window.Window)
box.SetVisible(false)
})
box.AddController(gesture1)
box.AddController(gesture2)
menu.Append(box)
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
}
@@ -999,9 +1031,9 @@ func activate(app *gtk.Application) {
} else {
allowed = false
if result.Error != nil {
showErrorDialog(fmt.Errorf("%s: %s - %s", loadedLocale["discoFail"], result.Error.Reason, result.Error.Text))
showErrorDialog(fmt.Errorf("%s: %s - %s", loadedLocale["discoFail"], result.Error.Reason, result.Error.Text), win)
} else {
showErrorDialog(fmt.Errorf(loadedLocale["discoFail"]))
showErrorDialog(fmt.Errorf(loadedLocale["discoFail"]), win)
}
}
}
@@ -1227,7 +1259,7 @@ func activate(app *gtk.Application) {
err := sendMessage(client, current, message_type, t, "", "", exts)
if err != nil {
showErrorDialog(err)
showErrorDialog(err, &window.Window)
}
message_en.SetText("")
scrollToBottomAfterUpdate(scroller)
+14 -13
View File
@@ -7,22 +7,23 @@ import (
)
type chatTab struct {
isMuc bool
msgs *gtk.ListBox
name string
isMuc bool
msgs *gtk.ListBox
name string
current_nick string
}
type lambdaConfig struct {
Server string
Username string
Resource string
Password string
Insecure bool
Nick string
JoinBookmarks bool
CVD color.CVD
Identicons bool
Debug bool
Server string
Username string
Resource string
Password string
Insecure bool
Nick string
JoinBookmarks bool
CVD color.CVD
Identicons bool
Debug bool
ShowPresenceUpdates bool
}