rotund
This commit is contained in:
@@ -153,7 +153,9 @@ var updateBytes []byte
|
||||
//go:embed assets/solar.png
|
||||
var solarBytes []byte
|
||||
|
||||
// var clientAssets map[string]gdk.Paintabler = make(map[string]gdk.Paintabler)
|
||||
//go:embed assets/timeline_marker.png
|
||||
var timelineMarkerBytes []byte
|
||||
|
||||
var clientAssets sync.Map
|
||||
|
||||
func loadAsset(key string, data []byte) {
|
||||
@@ -227,6 +229,7 @@ func init() {
|
||||
"please_wait": pleaseWaitBytes,
|
||||
"update": updateBytes,
|
||||
"solar": solarBytes,
|
||||
"timeline_marker": timelineMarkerBytes,
|
||||
} {
|
||||
loadAsset(key, data)
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 226 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 327 B |
@@ -6,7 +6,7 @@ require (
|
||||
github.com/BurntSushi/toml v1.6.0
|
||||
github.com/boxes-ltd/imaging v1.7.5
|
||||
github.com/crazy3lf/colorconv v1.2.0
|
||||
github.com/diamondburned/gotk4/pkg v0.3.1
|
||||
github.com/diamondburned/gotk4/pkg v0.4.1
|
||||
github.com/gen2brain/beeep v0.11.2
|
||||
github.com/go-analyze/charts v0.6.0
|
||||
github.com/google/uuid v1.6.0
|
||||
@@ -16,32 +16,30 @@ require (
|
||||
github.com/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d
|
||||
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c
|
||||
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef
|
||||
golang.org/x/net v0.57.0
|
||||
gosrc.io/xmpp v0.5.1
|
||||
mellium.im/xmpp v0.23.0
|
||||
)
|
||||
|
||||
require (
|
||||
git.sr.ht/~jackmordaunt/go-toast v1.1.2 // indirect
|
||||
github.com/KarpelesLab/weak v0.1.1 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/esiqveland/notify v0.14.0 // indirect
|
||||
github.com/go-analyze/bulk v0.1.4 // indirect
|
||||
github.com/go-analyze/bulk v0.1.5 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.2.2 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/jackmordaunt/icns/v3 v3.0.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/rogpeppe/go-internal v1.15.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.16.0 // indirect
|
||||
github.com/sergeymakinen/go-bmp v1.0.0 // indirect
|
||||
github.com/sergeymakinen/go-ico v1.0.0 // indirect
|
||||
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect
|
||||
go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6 // indirect
|
||||
golang.org/x/image v0.44.0 // indirect
|
||||
golang.org/x/image v0.45.0 // indirect
|
||||
golang.org/x/net v0.57.0 // indirect
|
||||
golang.org/x/sync v0.22.0 // indirect
|
||||
golang.org/x/sys v0.47.0 // indirect
|
||||
golang.org/x/text v0.40.0 // indirect
|
||||
golang.org/x/text v0.41.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
||||
mellium.im/reader v0.1.0 // indirect
|
||||
mellium.im/xmlstream v0.15.4 // indirect
|
||||
|
||||
@@ -2,8 +2,6 @@ git.sr.ht/~jackmordaunt/go-toast v1.1.2 h1:/yrfI55LRt1M7H1vkaw+NaH1+L1CDxrqDltwm
|
||||
git.sr.ht/~jackmordaunt/go-toast v1.1.2/go.mod h1:jA4OqHKTQ4AFBdwrSnwnskUIIS3HYzlJSgdzCKqfavo=
|
||||
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
|
||||
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/KarpelesLab/weak v0.1.1 h1:fNnlPo3aypS9tBzoEQluY13XyUfd/eWaSE/vMvo9s4g=
|
||||
github.com/KarpelesLab/weak v0.1.1/go.mod h1:pzXsWs5f2bf+fpgHayTlBE1qJpO3MpJKo5sRaLu1XNw=
|
||||
github.com/boxes-ltd/imaging v1.7.5 h1:k4kYxJEhysoGhEEN1IEeKoSbnG8/8snjj7M48Ok0fnk=
|
||||
github.com/boxes-ltd/imaging v1.7.5/go.mod h1:+8H+oRvis3InOFtTpcoCCB1RDXqo6p9tQBtjZfWnrC8=
|
||||
github.com/crazy3lf/colorconv v1.2.0 h1:UM7kSZWnwFMGiC+PpYrjxQSOd6sEyWb+dRKKTd3KslA=
|
||||
@@ -12,16 +10,16 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/diamondburned/gotk4/pkg v0.3.1 h1:uhkXSUPUsCyz3yujdvl7DSN8jiLS2BgNTQE95hk6ygg=
|
||||
github.com/diamondburned/gotk4/pkg v0.3.1/go.mod h1:DqeOW+MxSZFg9OO+esk4JgQk0TiUJJUBfMltKhG+ub4=
|
||||
github.com/diamondburned/gotk4/pkg v0.4.1 h1:w4BwVUUBkKyNLz5HKHN2Oz3kZCTLHfpfKgB/su1p6uo=
|
||||
github.com/diamondburned/gotk4/pkg v0.4.1/go.mod h1:BAEEDXtj5srQ1S2++5HX2K1s9c6CtuWSa60dAywrkRM=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/esiqveland/notify v0.14.0 h1:LgIT/vYnziiw3d4ykaeyytc7jBUhD+Nvv3U7GIuPFj4=
|
||||
github.com/esiqveland/notify v0.14.0/go.mod h1:hesw/IRYTO0x99u1JPweAl4+5mwXJibQVUcP0Iu5ORE=
|
||||
github.com/gen2brain/beeep v0.11.2 h1:+KfiKQBbQCuhfJFPANZuJ+oxsSKAYNe88hIpJuyKWDA=
|
||||
github.com/gen2brain/beeep v0.11.2/go.mod h1:jQVvuwnLuwOcdctHn/uyh8horSBNJ8uGb9Cn2W4tvoc=
|
||||
github.com/go-analyze/bulk v0.1.4 h1:PIlVl+KA73nW2KKr8eGiF3fhwfI1yAkTsur/3hzBM10=
|
||||
github.com/go-analyze/bulk v0.1.4/go.mod h1:afon/KtFJYnekIyN20H/+XUvcLFjE8sKR1CfpqfClgM=
|
||||
github.com/go-analyze/bulk v0.1.5 h1:Zj8w3gEOhEnp8aRZ7DHMDqaG3/Bp7CvQ7pu6Mw9YhFc=
|
||||
github.com/go-analyze/bulk v0.1.5/go.mod h1:afon/KtFJYnekIyN20H/+XUvcLFjE8sKR1CfpqfClgM=
|
||||
github.com/go-analyze/charts v0.6.0 h1:aBE2cbdr58faYGwPk3RUzGQMyg5fGsSAxepwYTYmvhg=
|
||||
github.com/go-analyze/charts v0.6.0/go.mod h1:m8hqGNSpYYdMMc0Im/RCowY9CIA7705jiltuOVQZWuI=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
@@ -51,8 +49,8 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.15.0 h1:D0RCU5rMAp+SpgkiNdrjfJ+LX4J1M32V2NeCY7EJ6hc=
|
||||
github.com/rogpeppe/go-internal v1.15.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs=
|
||||
github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g=
|
||||
github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs=
|
||||
github.com/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d h1:l3+2LWCbVxn5itfvXAfH9n4YL9jh8l1g5zcncbIc1cs=
|
||||
github.com/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d/go.mod h1:TbpErkob6SY7cyozRVSGoB3OlO2qOAgVN8O3KAJ4fMI=
|
||||
github.com/sergeymakinen/go-bmp v1.0.0 h1:SdGTzp9WvCV0A1V0mBeaS7kQAwNLdVJbmHlqNWq0R+M=
|
||||
@@ -73,14 +71,12 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk=
|
||||
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o=
|
||||
go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6 h1:lGdhQUN/cnWdSH3291CUuxSEqc+AsGTiDxPP3r2J0l4=
|
||||
go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
|
||||
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
||||
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
||||
golang.org/x/image v0.44.0 h1:+tDekMZED9+LrtB3G5xzRggpVh9CARjZqROla3R3R+I=
|
||||
golang.org/x/image v0.44.0/go.mod h1:V8K3KE9KKKE+pLpQDOeN18w9oacNSvy1tDOirTu4xtY=
|
||||
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
||||
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
||||
golang.org/x/image v0.45.0 h1:FMb1nTbH5H9vF55SriQHgFw5GnNL9Jg6L25BwXKzhB0=
|
||||
golang.org/x/image v0.45.0/go.mod h1:n62x/7RqlwXDvGsSU4u6IUTUf6KghUZ9Bt7cG/T9Fx4=
|
||||
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
|
||||
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
|
||||
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
|
||||
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
|
||||
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
|
||||
@@ -88,10 +84,10 @@ golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
|
||||
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
|
||||
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
|
||||
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
|
||||
golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
|
||||
golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
|
||||
golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
|
||||
golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY=
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
+7
-6
@@ -257,14 +257,14 @@ func createTab(jid string, isMuc bool, name string) bool {
|
||||
if !ok && !uok && !mok {
|
||||
newTab := new(chatTab)
|
||||
newTab.isMuc = isMuc
|
||||
newTab.msgs = gtk.NewListBox()
|
||||
glib.IdleAdd(func() {
|
||||
newTab.msgs = gtk.NewListBox()
|
||||
newTab.msgs.SetVExpand(true)
|
||||
newTab.msgs.SetShowSeparators(true)
|
||||
// newTab.msgs.Append(gtk.NewButtonWithLabel(loadedLocale["getPastMessages"]))
|
||||
})
|
||||
newTab.name = name
|
||||
|
||||
newTab.msg_refsID = make(map[string]*abMessage)
|
||||
tabs.Store(jid, newTab)
|
||||
return true
|
||||
}
|
||||
@@ -646,15 +646,14 @@ func switchToTab(jid string, w *gtk.Window) {
|
||||
|
||||
muc_presence := typed_tab.muc_presence
|
||||
muci := gtk.NewImage()
|
||||
muci.SetPixelSize(80)
|
||||
gen.Prepend(muci)
|
||||
|
||||
createIdenticon(jid, true, muci)
|
||||
if muc_presence != nil {
|
||||
vc := &VCardUpdate{}
|
||||
ok = muc_presence.Get(vc)
|
||||
if ok {
|
||||
getAvatar(jid, vc.Photo, muci)
|
||||
muci.SetPixelSize(80)
|
||||
gen.Prepend(muci)
|
||||
go getAvatar(jid, vc.Photo, muci)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -723,8 +722,10 @@ func createIdenticon(word string, always_create bool, i *gtk.Image) { // This fu
|
||||
return i
|
||||
*/
|
||||
|
||||
glib.IdleAdd(func() {
|
||||
i.SetFromPaintable(gt)
|
||||
i.AddCSSClass(loadedConfig.CVD.String() + "_CVD")
|
||||
})
|
||||
}
|
||||
|
||||
func jidBuilder(en *gtk.Entry) { // This function spawns a window that allows the user to interactively build a JID
|
||||
|
||||
+24
-9
@@ -74,7 +74,7 @@ func generatePresenceWidget(p stanza.Packet) gtk.Widgetter {
|
||||
return b
|
||||
}
|
||||
|
||||
func generateMessageWidget(p stanza.Packet, blocked bool) (gtk.Widgetter, bool) {
|
||||
func generateMessageWidget(p stanza.Packet, blocked bool, target string) (gtk.Widgetter, bool) {
|
||||
m, ok := p.(stanza.Message)
|
||||
if !ok {
|
||||
return gtk.NewLabel("Unsupported message."), true
|
||||
@@ -107,6 +107,13 @@ func generateMessageWidget(p stanza.Packet, blocked bool) (gtk.Widgetter, bool)
|
||||
return error_box, true
|
||||
}
|
||||
|
||||
store_label := false
|
||||
tab, ok := tabs.Load(target)
|
||||
if ok {
|
||||
store_label = true
|
||||
}
|
||||
typed_tab := tab.(*chatTab)
|
||||
|
||||
sid := StanzaID{}
|
||||
m.Get(&sid)
|
||||
|
||||
@@ -257,7 +264,7 @@ func generateMessageWidget(p stanza.Packet, blocked bool) (gtk.Widgetter, bool)
|
||||
mainBox.Append(al)
|
||||
|
||||
body := m.Body
|
||||
body = XEPToPango(body)
|
||||
body = XEPToPango(body, false)
|
||||
|
||||
mlabel := gtk.NewLabel("")
|
||||
mlabel.SetMarkup(body)
|
||||
@@ -266,6 +273,11 @@ func generateMessageWidget(p stanza.Packet, blocked bool) (gtk.Widgetter, bool)
|
||||
mlabel.SetSelectable(true)
|
||||
// mlabel.SetHAlign(gtk.AlignFill)
|
||||
mainBox.Append(mlabel)
|
||||
|
||||
if store_label {
|
||||
typed_tab.msg_refsID[m.Id].label_ref = mlabel
|
||||
tabs.Store(target, tab)
|
||||
}
|
||||
} else {
|
||||
authorBox := gtk.NewBox(gtk.OrientationHorizontal, 10)
|
||||
contentBox := gtk.NewBox(gtk.OrientationHorizontal, 0)
|
||||
@@ -332,7 +344,7 @@ func generateMessageWidget(p stanza.Packet, blocked bool) (gtk.Widgetter, bool)
|
||||
}
|
||||
|
||||
body := m.Body
|
||||
body = XEPToPango(body)
|
||||
body = XEPToPango(body, false)
|
||||
|
||||
mlabel := gtk.NewLabel("")
|
||||
if m.Body == "" {
|
||||
@@ -348,14 +360,17 @@ func generateMessageWidget(p stanza.Packet, blocked bool) (gtk.Widgetter, bool)
|
||||
mlabel.SetSelectable(true)
|
||||
mlabel.SetHAlign(gtk.AlignFill)
|
||||
|
||||
/*
|
||||
mum := MucUser{}
|
||||
ok = m.Get(&mum)
|
||||
if ok {
|
||||
mlabel.SetText(fmt.Sprintf("%s%s%s", mum.MucUserItem.JID, loadedLocale["affilChange"], mum.MucUserItem.Affiliation))
|
||||
if store_label {
|
||||
msg, ok := typed_tab.msg_refsID[m.Id]
|
||||
if !ok {
|
||||
msg = new(abMessage)
|
||||
typed_tab.msg_refsID[m.Id] = msg
|
||||
}
|
||||
*/
|
||||
|
||||
msg.label_ref = mlabel
|
||||
msg.ocu_id = ocu.ID
|
||||
tabs.Store(target, typed_tab)
|
||||
}
|
||||
contentBox.Append(mlabel)
|
||||
|
||||
mainBox.Append(authorBox)
|
||||
|
||||
+7
-3
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -14,7 +15,7 @@ var (
|
||||
codeRE = regexp.MustCompile("`([^`]+)`")
|
||||
)
|
||||
|
||||
func XEPToPango(text string) string {
|
||||
func XEPToPango(text string, correction bool) string {
|
||||
formatInline := func(s string) string {
|
||||
s = html.EscapeString(s)
|
||||
s = boldRE.ReplaceAllString(s, "<b>$1</b>")
|
||||
@@ -24,7 +25,6 @@ func XEPToPango(text string) string {
|
||||
return s
|
||||
}
|
||||
|
||||
|
||||
format := func(s string) string {
|
||||
lines := strings.Split(s, "\n")
|
||||
|
||||
@@ -56,5 +56,9 @@ func XEPToPango(text string) string {
|
||||
|
||||
b.WriteString(format(text[last:]))
|
||||
|
||||
return b.String()
|
||||
str := b.String()
|
||||
if correction {
|
||||
str = fmt.Sprintf("%s %s", str, loadedLocale["correction"])
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ var enGB = map[string]string{ // British English
|
||||
"joinMUCJIDEntry": "MUC JID:",
|
||||
"joinMUCNickEntry": "Nick:",
|
||||
"joinMUCDiscoCheck": "Check MUC features before joining",
|
||||
"joinMUCBookmarkCheck": "Add to bookmarks",
|
||||
"joinMUCDiscoCheckTooltip": "If you are creating a MUC through this window then turn this off",
|
||||
"joinPreviewTitle": "Joining ",
|
||||
"joinPasswordRequired": "Password required",
|
||||
@@ -91,7 +92,7 @@ var enGB = map[string]string{ // British English
|
||||
"affiliatedAs": "Affiliated as ",
|
||||
"unaffiliated": "Unaffiliated",
|
||||
"participants": "participant(s)",
|
||||
"versionQueryEmpty": "Client responded with empty version",
|
||||
"versionQueryEmpty": "You do not have permission to view this client's version",
|
||||
"versionQueryError": "Got error trying to get version",
|
||||
|
||||
"away": "Away",
|
||||
@@ -118,6 +119,9 @@ var enGB = map[string]string{ // British English
|
||||
"updateSave": "Lambda %s check the upstream server for updates. You can change this at any time via preferences.",
|
||||
"updateWill": "will",
|
||||
"updateWont": "won't",
|
||||
|
||||
// gtk-xmpp-markup.go
|
||||
"correction": "<span foreground=\"grey\" size=\"x-small\">[corrected] </span>",
|
||||
}
|
||||
|
||||
var kaGE = map[string]string{ // Georgian (Georgia)
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"github.com/gen2brain/beeep"
|
||||
"github.com/go-analyze/charts"
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/net/html/charset"
|
||||
|
||||
"time"
|
||||
|
||||
@@ -28,7 +27,6 @@ import (
|
||||
|
||||
_ "embed"
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"runtime"
|
||||
|
||||
"github.com/kr/pretty"
|
||||
@@ -44,6 +42,9 @@ var connectionIcon *gtk.Image
|
||||
var mStatus *gtk.Label
|
||||
var mIcon *gtk.Image
|
||||
|
||||
var gStatus *gtk.Label
|
||||
var gIcon *gtk.Image
|
||||
|
||||
/*
|
||||
var sStatus *gtk.Label
|
||||
var sIcon *gtk.Image
|
||||
@@ -142,9 +143,6 @@ func main() {
|
||||
config := xmpp.Config{
|
||||
TransportConfiguration: xmpp.TransportConfiguration{
|
||||
Address: loadedConfig.Server,
|
||||
CharsetReader: func(c string, input io.Reader) (io.Reader, error) {
|
||||
return charset.NewReaderLabel(c, input)
|
||||
},
|
||||
ConnectTimeout: 300,
|
||||
TLSConfig: &tls.Config{InsecureSkipVerify: loadedConfig.Insecure},
|
||||
},
|
||||
@@ -170,15 +168,14 @@ func main() {
|
||||
|
||||
// All requests from either ourselves or our server will always be accepted regardless of user settings.
|
||||
|
||||
|
||||
if !(loadedConfig.DiscoPrivacy == 0) && !((JidMustParse(iq.From).Bare() == JidMustParse(clientroot.Session.BindJid).Bare()) || (JidMustParse(iq.From).Domain == JidMustParse(clientroot.Session.BindJid).Domain)) {
|
||||
if loadedConfig.DiscoPrivacy == None || (loadedConfig.DiscoPrivacy == OnlyRoster && !Roster[JidMustParse(iq.From).Bare()]) {
|
||||
fmt.Println("blocking", loadedConfig.DiscoPrivacy)
|
||||
if loadedConfig.IgnoreInsteadOfReturnErrorUponPrivacyViolation {
|
||||
return
|
||||
}
|
||||
|
||||
iqResp.Type = "error"
|
||||
iqResp.From = clientroot.Session.BindJid
|
||||
|
||||
stanza_err := new(stanza.Err)
|
||||
stanza_err.Type = stanza.ErrorTypeCancel
|
||||
@@ -190,7 +187,6 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
identity := stanza.Identity{
|
||||
Name: "Lambda",
|
||||
Category: "client", // TODO: Allow spoofing on user request
|
||||
@@ -235,12 +231,12 @@ func main() {
|
||||
|
||||
if !(loadedConfig.VersionPrivacy == 0) && !((JidMustParse(iq.From).Bare() == JidMustParse(clientroot.Session.BindJid).Bare()) || (JidMustParse(iq.From).Domain == JidMustParse(clientroot.Session.BindJid).Domain)) {
|
||||
if loadedConfig.VersionPrivacy == None || (loadedConfig.VersionPrivacy == OnlyRoster && !Roster[JidMustParse(iq.From).Bare()]) {
|
||||
fmt.Println("blocking", loadedConfig.DiscoPrivacy)
|
||||
if loadedConfig.IgnoreInsteadOfReturnErrorUponPrivacyViolation {
|
||||
return
|
||||
}
|
||||
|
||||
iqResp.Type = "error"
|
||||
iqResp.From = clientroot.Session.BindJid
|
||||
|
||||
stanza_err := new(stanza.Err)
|
||||
stanza_err.Type = stanza.ErrorTypeCancel
|
||||
@@ -283,6 +279,7 @@ func main() {
|
||||
}
|
||||
|
||||
originator := JidMustParse(m.From).Bare()
|
||||
|
||||
glib.IdleAdd(func() {
|
||||
mStatus.SetText(originator)
|
||||
})
|
||||
@@ -345,6 +342,28 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
// Handle corrections BEFORE attempting to generate a message
|
||||
correction := new(Correction)
|
||||
ok = m.Get(correction)
|
||||
if ok {
|
||||
tab, ok := tabs.Load(originator)
|
||||
if ok {
|
||||
typed_tab := tab.(*chatTab)
|
||||
if ok {
|
||||
msg, ok := typed_tab.msg_refsID[correction.ID]
|
||||
if ok {
|
||||
if msg.ocu_id == oi.ID && msg.ocu_id != "" {
|
||||
lab := msg.label_ref
|
||||
glib.IdleAdd(func() {
|
||||
lab.SetMarkup(XEPToPango(m.Body, true))
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glib.IdleAdd(func() {
|
||||
b := gtk.NewBox(gtk.OrientationVertical, 0)
|
||||
|
||||
@@ -363,7 +382,7 @@ func main() {
|
||||
fmt.Println("Got message when the tab does not exist!")
|
||||
}
|
||||
|
||||
untyped_box, valid := generateMessageWidget(p, blocked)
|
||||
untyped_box, valid := generateMessageWidget(p, blocked, originator)
|
||||
ba, converted_successfully := untyped_box.(*gtk.Box)
|
||||
|
||||
if valid && converted_successfully {
|
||||
@@ -505,11 +524,18 @@ func main() {
|
||||
// client = c
|
||||
// clientroot = c
|
||||
|
||||
// Ping
|
||||
go func() {
|
||||
for {
|
||||
time.Sleep(5 * time.Second)
|
||||
go func() {
|
||||
// Goroutine counter
|
||||
goroutines := runtime.NumGoroutine()
|
||||
glib.IdleAdd(func() {
|
||||
gStatus.SetText(fmt.Sprintf("%d goroutines", goroutines))
|
||||
})
|
||||
}()
|
||||
go func() {
|
||||
// Ping
|
||||
pingStatus.AddCSSClass("pending")
|
||||
before := time.Now()
|
||||
iq := new(stanza.IQ)
|
||||
@@ -971,10 +997,12 @@ func activate(app *gtk.Application) {
|
||||
jid_box := gtk.NewBox(gtk.OrientationHorizontal, 10)
|
||||
nick_box := gtk.NewBox(gtk.OrientationHorizontal, 10)
|
||||
disco_box := gtk.NewBox(gtk.OrientationHorizontal, 10)
|
||||
bookmark_box := gtk.NewBox(gtk.OrientationHorizontal, 10)
|
||||
|
||||
jid_entry := gtk.NewEntry()
|
||||
nick_entry := gtk.NewEntry()
|
||||
disco_check := gtk.NewCheckButton()
|
||||
bookmark_check := gtk.NewCheckButton()
|
||||
|
||||
jid_entry.SetHAlign(gtk.AlignEnd)
|
||||
jid_entry.SetHExpand(true)
|
||||
@@ -1004,9 +1032,14 @@ func activate(app *gtk.Application) {
|
||||
disco_box.Append(disco_check)
|
||||
disco_box.SetTooltipText(loadedLocale["joinMUCDiscoCheckTooltip"])
|
||||
|
||||
bookmark_check.SetActive(true)
|
||||
bookmark_box.Append(gtk.NewLabel(loadedLocale["joinMUCBookmarkCheck"]))
|
||||
bookmark_box.Append(bookmark_check)
|
||||
|
||||
box.Append(jid_box)
|
||||
box.Append(nick_box)
|
||||
box.Append(disco_box)
|
||||
box.Append(bookmark_box)
|
||||
|
||||
btn := gtk.NewButtonWithLabel(loadedLocale["submit"])
|
||||
btn.SetVAlign(gtk.AlignBaseline)
|
||||
@@ -1035,15 +1068,7 @@ func activate(app *gtk.Application) {
|
||||
im.SetPixelSize(40)
|
||||
|
||||
go getAvatar(t, t, im)
|
||||
/*
|
||||
go func() {
|
||||
new_im := getAvatar(t, t)
|
||||
glib.IdleAdd(func() {
|
||||
new_im.SetPixelSize(40)
|
||||
box.Prepend(new_im)
|
||||
})
|
||||
}()
|
||||
*/
|
||||
|
||||
b := gtk.NewLabel(n)
|
||||
|
||||
box.Append(im)
|
||||
@@ -1065,6 +1090,13 @@ func activate(app *gtk.Application) {
|
||||
box.AddController(gesture2)
|
||||
menu.Append(box)
|
||||
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
|
||||
|
||||
if bookmark_check.Active() {
|
||||
_, err := addPEPBookmark(client, t, n, nick_entry.Text(), true, pw)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
|
||||
@@ -1092,12 +1124,13 @@ func activate(app *gtk.Application) {
|
||||
|
||||
myIQ.Payload = &stanza.DiscoInfo{}
|
||||
|
||||
ctx := context.TODO()
|
||||
ctx := context.Background()
|
||||
mychan, err := client.SendIQ(ctx, myIQ)
|
||||
if err == nil {
|
||||
result := <-mychan
|
||||
res, ok = result.Payload.(*stanza.DiscoInfo)
|
||||
if ok {
|
||||
if len(res.Identity) >= 1 {
|
||||
features := res.Features
|
||||
allowed = false
|
||||
password_protected := false
|
||||
@@ -1197,6 +1230,10 @@ func activate(app *gtk.Application) {
|
||||
warning_box.Append(buttons)
|
||||
warning_win.SetChild(warning_box)
|
||||
warning_win.Present()
|
||||
} else {
|
||||
allowed = false
|
||||
showErrorDialog(fmt.Errorf(loadedLocale["discoFail"]), win)
|
||||
}
|
||||
} else {
|
||||
allowed = false
|
||||
if result.Error != nil {
|
||||
@@ -1274,9 +1311,16 @@ func activate(app *gtk.Application) {
|
||||
mStatus = gtk.NewLabel("-")
|
||||
mStatus.AddController(gesture1)
|
||||
|
||||
gIcon = gtk.NewImageFromPaintable((clientAssetsLoad("timeline_marker")))
|
||||
gIcon.AddCSSClass("icon")
|
||||
gStatus = gtk.NewLabel("...")
|
||||
|
||||
cBox.Append(mIcon)
|
||||
cBox.Append(mStatus)
|
||||
|
||||
cBox.Append(gIcon)
|
||||
cBox.Append(gStatus)
|
||||
|
||||
statBar.Append(mBox)
|
||||
|
||||
pBox := gtk.NewBox(gtk.OrientationHorizontal, 0)
|
||||
|
||||
@@ -112,3 +112,17 @@
|
||||
text-decoration: underline;
|
||||
color: green;
|
||||
}
|
||||
|
||||
.rainbow {
|
||||
background: linear-gradient(to right, #ef5350, #f48fb1, #7e57c2, #2196f3, #26c6da, #43a047, #eeff41, #f9a825, #ff5722);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.correction {
|
||||
font-style: italic;
|
||||
background-color: white;
|
||||
border-radius: 5px;
|
||||
color: black;
|
||||
|
||||
}
|
||||
|
||||
@@ -7,9 +7,15 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type abMessage struct {
|
||||
label_ref *gtk.Label
|
||||
ocu_id string
|
||||
}
|
||||
|
||||
type chatTab struct {
|
||||
isMuc bool
|
||||
msgs *gtk.ListBox
|
||||
msg_refsID map[string]*abMessage
|
||||
name string
|
||||
current_nick string
|
||||
muc_presence *stanza.Presence
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
package main
|
||||
|
||||
var lambda_version string = "7"
|
||||
var lambda_version string = "8"
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"gosrc.io/xmpp/stanza"
|
||||
)
|
||||
|
||||
@@ -17,6 +18,38 @@ type Bookmark struct {
|
||||
Extensions []any `xml:"extensions,omitempty"`
|
||||
}
|
||||
|
||||
func (b *Bookmark) ToNode() *stanza.Node {
|
||||
node := &stanza.Node{
|
||||
XMLName: xml.Name{Space: "urn:xmpp:bookmarks:1", Local: "conference"},
|
||||
Attrs: []xml.Attr{
|
||||
{Name: xml.Name{Local: "name"}, Value: b.Name},
|
||||
{Name: xml.Name{Local: "autojoin"}, Value: fmt.Sprintf("%t", b.Autojoin)},
|
||||
},
|
||||
}
|
||||
|
||||
if b.Nick != "" {
|
||||
node.Nodes = append(node.Nodes, stanza.Node{
|
||||
XMLName: xml.Name{Local: "nick"},
|
||||
Content: b.Nick,
|
||||
})
|
||||
}
|
||||
|
||||
if b.Password != "" {
|
||||
node.Nodes = append(node.Nodes, stanza.Node{
|
||||
XMLName: xml.Name{Local: "password"},
|
||||
Content: b.Password,
|
||||
})
|
||||
}
|
||||
|
||||
for _, ext := range b.Extensions {
|
||||
if extNode, ok := ext.(stanza.Node); ok {
|
||||
node.Nodes = append(node.Nodes, extNode)
|
||||
}
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
func init() {
|
||||
stanza.TypeRegistry.MapExtension(stanza.PKTIQ, xml.Name{Space: "urn:xmpp:bookmarks:1", Local: "conference"}, Bookmark{})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"gosrc.io/xmpp/stanza"
|
||||
)
|
||||
|
||||
// Implementation of XEP-0308: Last Message Correction
|
||||
// XEP is supposed to only allow you to correct last message and only show corrections to the user's last message
|
||||
// Unfortunately, I do not give a fuck and will let any messages be corrected
|
||||
|
||||
type Correction struct {
|
||||
stanza.MsgExtension
|
||||
XMLName xml.Name `xml:"urn:xmpp:message-correct:0 replace"`
|
||||
ID string `xml:"id,attr"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{Space: "urn:xmpp:message-correct:0", Local: "replace"}, Correction{})
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"gosrc.io/xmpp"
|
||||
"gosrc.io/xmpp/stanza"
|
||||
@@ -140,3 +141,62 @@ func sendVoiceRequest(c xmpp.Sender, sendTo string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addPEPBookmark(c xmpp.Sender, jid string, name string, nick string, autojoin bool, password string) (stanza.IQ, error) {
|
||||
item := new(stanza.Item)
|
||||
item.Id = jid
|
||||
|
||||
bookmark := Bookmark{}
|
||||
bookmark.Name = name
|
||||
bookmark.Autojoin = autojoin
|
||||
bookmark.Nick = nick
|
||||
bookmark.Password = password
|
||||
node := bookmark.ToNode()
|
||||
|
||||
options_form := new(stanza.Form)
|
||||
options_form.Type = "submit"
|
||||
|
||||
persist := new(stanza.Field)
|
||||
persist.Type = "boolean"
|
||||
persist.Var = "pubsub#persist_items"
|
||||
persist.ValuesList = []string{"true"}
|
||||
options_form.Fields = append(options_form.Fields, persist)
|
||||
|
||||
max_items := new(stanza.Field)
|
||||
max_items.Type = "text-single"
|
||||
max_items.Var = "pubsub#max_items"
|
||||
max_items.ValuesList = []string{"max"}
|
||||
options_form.Fields = append(options_form.Fields, max_items)
|
||||
|
||||
send_last_published_item := new(stanza.Field)
|
||||
send_last_published_item.Type = "text-single"
|
||||
send_last_published_item.Var = "pubsub#send_last_published_item"
|
||||
send_last_published_item.ValuesList = []string{"never"}
|
||||
options_form.Fields = append(options_form.Fields, send_last_published_item)
|
||||
|
||||
access_model := new(stanza.Field)
|
||||
access_model.Type = "text-single"
|
||||
access_model.Var = "pubsub#access_model"
|
||||
access_model.ValuesList = []string{"whitelist"}
|
||||
options_form.Fields = append(options_form.Fields, access_model)
|
||||
|
||||
options := new(stanza.PublishOptions)
|
||||
options.Form = options_form
|
||||
|
||||
item.Any = node
|
||||
items := []stanza.Item{*item}
|
||||
pubsub, err := stanza.NewPublishItemOptsRq("", "urn:xmpp:bookmarks:1", items, options)
|
||||
if err != nil {
|
||||
return stanza.IQ{}, err
|
||||
}
|
||||
ctx := context.TODO()
|
||||
|
||||
channel, err := c.SendIQ(ctx, pubsub)
|
||||
if err != nil {
|
||||
return stanza.IQ{}, err
|
||||
}
|
||||
|
||||
result := <-channel
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user