This commit is contained in:
2026-08-16 20:07:53 +01:00
parent eebb6906c6
commit 58ae55e061
16 changed files with 369 additions and 171 deletions
+4 -1
View File
@@ -153,7 +153,9 @@ var updateBytes []byte
//go:embed assets/solar.png //go:embed assets/solar.png
var solarBytes []byte 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 var clientAssets sync.Map
func loadAsset(key string, data []byte) { func loadAsset(key string, data []byte) {
@@ -227,6 +229,7 @@ func init() {
"please_wait": pleaseWaitBytes, "please_wait": pleaseWaitBytes,
"update": updateBytes, "update": updateBytes,
"solar": solarBytes, "solar": solarBytes,
"timeline_marker": timelineMarkerBytes,
} { } {
loadAsset(key, data) loadAsset(key, data)
} }
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

+6 -8
View File
@@ -6,7 +6,7 @@ require (
github.com/BurntSushi/toml v1.6.0 github.com/BurntSushi/toml v1.6.0
github.com/boxes-ltd/imaging v1.7.5 github.com/boxes-ltd/imaging v1.7.5
github.com/crazy3lf/colorconv v1.2.0 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/gen2brain/beeep v0.11.2
github.com/go-analyze/charts v0.6.0 github.com/go-analyze/charts v0.6.0
github.com/google/uuid v1.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/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef
golang.org/x/net v0.57.0
gosrc.io/xmpp v0.5.1 gosrc.io/xmpp v0.5.1
mellium.im/xmpp v0.23.0 mellium.im/xmpp v0.23.0
) )
require ( require (
git.sr.ht/~jackmordaunt/go-toast v1.1.2 // indirect 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/dustin/go-humanize v1.0.1 // indirect
github.com/esiqveland/notify v0.14.0 // 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/go-ole/go-ole v1.3.0 // indirect
github.com/godbus/dbus/v5 v5.2.2 // indirect github.com/godbus/dbus/v5 v5.2.2 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/jackmordaunt/icns/v3 v3.0.1 // indirect github.com/jackmordaunt/icns/v3 v3.0.1 // indirect
github.com/kr/text v0.2.0 // indirect github.com/kr/text v0.2.0 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // 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-bmp v1.0.0 // indirect
github.com/sergeymakinen/go-ico v1.0.0 // indirect github.com/sergeymakinen/go-ico v1.0.0 // indirect
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // 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.45.0 // indirect
golang.org/x/image v0.44.0 // indirect golang.org/x/net v0.57.0 // indirect
golang.org/x/sync v0.22.0 // indirect golang.org/x/sync v0.22.0 // indirect
golang.org/x/sys v0.47.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 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
mellium.im/reader v0.1.0 // indirect mellium.im/reader v0.1.0 // indirect
mellium.im/xmlstream v0.15.4 // indirect mellium.im/xmlstream v0.15.4 // indirect
+14 -18
View File
@@ -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= 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 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= 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 h1:k4kYxJEhysoGhEEN1IEeKoSbnG8/8snjj7M48Ok0fnk=
github.com/boxes-ltd/imaging v1.7.5/go.mod h1:+8H+oRvis3InOFtTpcoCCB1RDXqo6p9tQBtjZfWnrC8= github.com/boxes-ltd/imaging v1.7.5/go.mod h1:+8H+oRvis3InOFtTpcoCCB1RDXqo6p9tQBtjZfWnrC8=
github.com/crazy3lf/colorconv v1.2.0 h1:UM7kSZWnwFMGiC+PpYrjxQSOd6sEyWb+dRKKTd3KslA= 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.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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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.4.1 h1:w4BwVUUBkKyNLz5HKHN2Oz3kZCTLHfpfKgB/su1p6uo=
github.com/diamondburned/gotk4/pkg v0.3.1/go.mod h1:DqeOW+MxSZFg9OO+esk4JgQk0TiUJJUBfMltKhG+ub4= 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 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= 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 h1:LgIT/vYnziiw3d4ykaeyytc7jBUhD+Nvv3U7GIuPFj4=
github.com/esiqveland/notify v0.14.0/go.mod h1:hesw/IRYTO0x99u1JPweAl4+5mwXJibQVUcP0Iu5ORE= 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 h1:+KfiKQBbQCuhfJFPANZuJ+oxsSKAYNe88hIpJuyKWDA=
github.com/gen2brain/beeep v0.11.2/go.mod h1:jQVvuwnLuwOcdctHn/uyh8horSBNJ8uGb9Cn2W4tvoc= 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.5 h1:Zj8w3gEOhEnp8aRZ7DHMDqaG3/Bp7CvQ7pu6Mw9YhFc=
github.com/go-analyze/bulk v0.1.4/go.mod h1:afon/KtFJYnekIyN20H/+XUvcLFjE8sKR1CfpqfClgM= 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 h1:aBE2cbdr58faYGwPk3RUzGQMyg5fGsSAxepwYTYmvhg=
github.com/go-analyze/charts v0.6.0/go.mod h1:m8hqGNSpYYdMMc0Im/RCowY9CIA7705jiltuOVQZWuI= 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= 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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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.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.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g=
github.com/rogpeppe/go-internal v1.15.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs= 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 h1:l3+2LWCbVxn5itfvXAfH9n4YL9jh8l1g5zcncbIc1cs=
github.com/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d/go.mod h1:TbpErkob6SY7cyozRVSGoB3OlO2qOAgVN8O3KAJ4fMI= github.com/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d/go.mod h1:TbpErkob6SY7cyozRVSGoB3OlO2qOAgVN8O3KAJ4fMI=
github.com/sergeymakinen/go-bmp v1.0.0 h1:SdGTzp9WvCV0A1V0mBeaS7kQAwNLdVJbmHlqNWq0R+M= 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/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 h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk=
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o= 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 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk= 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.45.0 h1:FMb1nTbH5H9vF55SriQHgFw5GnNL9Jg6L25BwXKzhB0=
golang.org/x/image v0.44.0/go.mod h1:V8K3KE9KKKE+pLpQDOeN18w9oacNSvy1tDOirTu4xtY= golang.org/x/image v0.45.0/go.mod h1:n62x/7RqlwXDvGsSU4u6IUTUf6KghUZ9Bt7cG/T9Fx4=
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= 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 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= 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.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= 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.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q= golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA= 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 h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY=
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= 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= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+9 -8
View File
@@ -257,14 +257,14 @@ func createTab(jid string, isMuc bool, name string) bool {
if !ok && !uok && !mok { if !ok && !uok && !mok {
newTab := new(chatTab) newTab := new(chatTab)
newTab.isMuc = isMuc newTab.isMuc = isMuc
newTab.msgs = gtk.NewListBox()
glib.IdleAdd(func() { glib.IdleAdd(func() {
newTab.msgs = gtk.NewListBox()
newTab.msgs.SetVExpand(true) newTab.msgs.SetVExpand(true)
newTab.msgs.SetShowSeparators(true) newTab.msgs.SetShowSeparators(true)
// newTab.msgs.Append(gtk.NewButtonWithLabel(loadedLocale["getPastMessages"])) // newTab.msgs.Append(gtk.NewButtonWithLabel(loadedLocale["getPastMessages"]))
}) })
newTab.name = name newTab.name = name
newTab.msg_refsID = make(map[string]*abMessage)
tabs.Store(jid, newTab) tabs.Store(jid, newTab)
return true return true
} }
@@ -646,15 +646,14 @@ func switchToTab(jid string, w *gtk.Window) {
muc_presence := typed_tab.muc_presence muc_presence := typed_tab.muc_presence
muci := gtk.NewImage() muci := gtk.NewImage()
muci.SetPixelSize(80)
gen.Prepend(muci)
createIdenticon(jid, true, muci)
if muc_presence != nil { if muc_presence != nil {
vc := &VCardUpdate{} vc := &VCardUpdate{}
ok = muc_presence.Get(vc) ok = muc_presence.Get(vc)
if ok { if ok {
getAvatar(jid, vc.Photo, muci) go getAvatar(jid, vc.Photo, muci)
muci.SetPixelSize(80)
gen.Prepend(muci)
} }
} }
@@ -723,8 +722,10 @@ func createIdenticon(word string, always_create bool, i *gtk.Image) { // This fu
return i return i
*/ */
i.SetFromPaintable(gt) glib.IdleAdd(func() {
i.AddCSSClass(loadedConfig.CVD.String() + "_CVD") 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 func jidBuilder(en *gtk.Entry) { // This function spawns a window that allows the user to interactively build a JID
+24 -9
View File
@@ -74,7 +74,7 @@ func generatePresenceWidget(p stanza.Packet) gtk.Widgetter {
return b 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) m, ok := p.(stanza.Message)
if !ok { if !ok {
return gtk.NewLabel("Unsupported message."), true return gtk.NewLabel("Unsupported message."), true
@@ -107,6 +107,13 @@ func generateMessageWidget(p stanza.Packet, blocked bool) (gtk.Widgetter, bool)
return error_box, true return error_box, true
} }
store_label := false
tab, ok := tabs.Load(target)
if ok {
store_label = true
}
typed_tab := tab.(*chatTab)
sid := StanzaID{} sid := StanzaID{}
m.Get(&sid) m.Get(&sid)
@@ -257,7 +264,7 @@ func generateMessageWidget(p stanza.Packet, blocked bool) (gtk.Widgetter, bool)
mainBox.Append(al) mainBox.Append(al)
body := m.Body body := m.Body
body = XEPToPango(body) body = XEPToPango(body, false)
mlabel := gtk.NewLabel("") mlabel := gtk.NewLabel("")
mlabel.SetMarkup(body) mlabel.SetMarkup(body)
@@ -266,6 +273,11 @@ func generateMessageWidget(p stanza.Packet, blocked bool) (gtk.Widgetter, bool)
mlabel.SetSelectable(true) mlabel.SetSelectable(true)
// mlabel.SetHAlign(gtk.AlignFill) // mlabel.SetHAlign(gtk.AlignFill)
mainBox.Append(mlabel) mainBox.Append(mlabel)
if store_label {
typed_tab.msg_refsID[m.Id].label_ref = mlabel
tabs.Store(target, tab)
}
} else { } else {
authorBox := gtk.NewBox(gtk.OrientationHorizontal, 10) authorBox := gtk.NewBox(gtk.OrientationHorizontal, 10)
contentBox := gtk.NewBox(gtk.OrientationHorizontal, 0) contentBox := gtk.NewBox(gtk.OrientationHorizontal, 0)
@@ -332,7 +344,7 @@ func generateMessageWidget(p stanza.Packet, blocked bool) (gtk.Widgetter, bool)
} }
body := m.Body body := m.Body
body = XEPToPango(body) body = XEPToPango(body, false)
mlabel := gtk.NewLabel("") mlabel := gtk.NewLabel("")
if m.Body == "" { if m.Body == "" {
@@ -348,14 +360,17 @@ func generateMessageWidget(p stanza.Packet, blocked bool) (gtk.Widgetter, bool)
mlabel.SetSelectable(true) mlabel.SetSelectable(true)
mlabel.SetHAlign(gtk.AlignFill) mlabel.SetHAlign(gtk.AlignFill)
/* if store_label {
mum := MucUser{} msg, ok := typed_tab.msg_refsID[m.Id]
ok = m.Get(&mum) if !ok {
if ok { msg = new(abMessage)
mlabel.SetText(fmt.Sprintf("%s%s%s", mum.MucUserItem.JID, loadedLocale["affilChange"], mum.MucUserItem.Affiliation)) typed_tab.msg_refsID[m.Id] = msg
} }
*/
msg.label_ref = mlabel
msg.ocu_id = ocu.ID
tabs.Store(target, typed_tab)
}
contentBox.Append(mlabel) contentBox.Append(mlabel)
mainBox.Append(authorBox) mainBox.Append(authorBox)
+8 -4
View File
@@ -1,6 +1,7 @@
package main package main
import ( import (
"fmt"
"html" "html"
"regexp" "regexp"
"strings" "strings"
@@ -14,7 +15,7 @@ var (
codeRE = regexp.MustCompile("`([^`]+)`") codeRE = regexp.MustCompile("`([^`]+)`")
) )
func XEPToPango(text string) string { func XEPToPango(text string, correction bool) string {
formatInline := func(s string) string { formatInline := func(s string) string {
s = html.EscapeString(s) s = html.EscapeString(s)
s = boldRE.ReplaceAllString(s, "<b>$1</b>") s = boldRE.ReplaceAllString(s, "<b>$1</b>")
@@ -24,13 +25,12 @@ func XEPToPango(text string) string {
return s return s
} }
format := func(s string) string { format := func(s string) string {
lines := strings.Split(s, "\n") lines := strings.Split(s, "\n")
for i, line := range lines { for i, line := range lines {
lines[i] = formatInline(line) lines[i] = formatInline(line)
} }
return strings.Join(lines, "\n") return strings.Join(lines, "\n")
@@ -56,5 +56,9 @@ func XEPToPango(text string) string {
b.WriteString(format(text[last:])) b.WriteString(format(text[last:]))
return b.String() str := b.String()
if correction {
str = fmt.Sprintf("%s %s", str, loadedLocale["correction"])
}
return str
} }
+5 -1
View File
@@ -29,6 +29,7 @@ var enGB = map[string]string{ // British English
"joinMUCJIDEntry": "MUC JID:", "joinMUCJIDEntry": "MUC JID:",
"joinMUCNickEntry": "Nick:", "joinMUCNickEntry": "Nick:",
"joinMUCDiscoCheck": "Check MUC features before joining", "joinMUCDiscoCheck": "Check MUC features before joining",
"joinMUCBookmarkCheck": "Add to bookmarks",
"joinMUCDiscoCheckTooltip": "If you are creating a MUC through this window then turn this off", "joinMUCDiscoCheckTooltip": "If you are creating a MUC through this window then turn this off",
"joinPreviewTitle": "Joining ", "joinPreviewTitle": "Joining ",
"joinPasswordRequired": "Password required", "joinPasswordRequired": "Password required",
@@ -91,7 +92,7 @@ var enGB = map[string]string{ // British English
"affiliatedAs": "Affiliated as ", "affiliatedAs": "Affiliated as ",
"unaffiliated": "Unaffiliated", "unaffiliated": "Unaffiliated",
"participants": "participant(s)", "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", "versionQueryError": "Got error trying to get version",
"away": "Away", "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.", "updateSave": "Lambda %s check the upstream server for updates. You can change this at any time via preferences.",
"updateWill": "will", "updateWill": "will",
"updateWont": "won't", "updateWont": "won't",
// gtk-xmpp-markup.go
"correction": "<span foreground=\"grey\" size=\"x-small\">[corrected] </span>",
} }
var kaGE = map[string]string{ // Georgian (Georgia) var kaGE = map[string]string{ // Georgian (Georgia)
+158 -114
View File
@@ -18,7 +18,6 @@ import (
"github.com/gen2brain/beeep" "github.com/gen2brain/beeep"
"github.com/go-analyze/charts" "github.com/go-analyze/charts"
"github.com/google/uuid" "github.com/google/uuid"
"golang.org/x/net/html/charset"
"time" "time"
@@ -28,7 +27,6 @@ import (
_ "embed" _ "embed"
"encoding/xml" "encoding/xml"
"io"
"runtime" "runtime"
"github.com/kr/pretty" "github.com/kr/pretty"
@@ -44,6 +42,9 @@ var connectionIcon *gtk.Image
var mStatus *gtk.Label var mStatus *gtk.Label
var mIcon *gtk.Image var mIcon *gtk.Image
var gStatus *gtk.Label
var gIcon *gtk.Image
/* /*
var sStatus *gtk.Label var sStatus *gtk.Label
var sIcon *gtk.Image var sIcon *gtk.Image
@@ -141,10 +142,7 @@ func main() {
config := xmpp.Config{ config := xmpp.Config{
TransportConfiguration: xmpp.TransportConfiguration{ TransportConfiguration: xmpp.TransportConfiguration{
Address: loadedConfig.Server, Address: loadedConfig.Server,
CharsetReader: func(c string, input io.Reader) (io.Reader, error) {
return charset.NewReaderLabel(c, input)
},
ConnectTimeout: 300, ConnectTimeout: 300,
TLSConfig: &tls.Config{InsecureSkipVerify: loadedConfig.Insecure}, 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. // 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 == 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()]) { if loadedConfig.DiscoPrivacy == None || (loadedConfig.DiscoPrivacy == OnlyRoster && !Roster[JidMustParse(iq.From).Bare()]) {
fmt.Println("blocking", loadedConfig.DiscoPrivacy)
if loadedConfig.IgnoreInsteadOfReturnErrorUponPrivacyViolation { if loadedConfig.IgnoreInsteadOfReturnErrorUponPrivacyViolation {
return return
} }
iqResp.Type = "error" iqResp.Type = "error"
iqResp.From = clientroot.Session.BindJid
stanza_err := new(stanza.Err) stanza_err := new(stanza.Err)
stanza_err.Type = stanza.ErrorTypeCancel stanza_err.Type = stanza.ErrorTypeCancel
@@ -190,7 +187,6 @@ func main() {
} }
} }
identity := stanza.Identity{ identity := stanza.Identity{
Name: "Lambda", Name: "Lambda",
Category: "client", // TODO: Allow spoofing on user request 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 == 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()]) { if loadedConfig.VersionPrivacy == None || (loadedConfig.VersionPrivacy == OnlyRoster && !Roster[JidMustParse(iq.From).Bare()]) {
fmt.Println("blocking", loadedConfig.DiscoPrivacy)
if loadedConfig.IgnoreInsteadOfReturnErrorUponPrivacyViolation { if loadedConfig.IgnoreInsteadOfReturnErrorUponPrivacyViolation {
return return
} }
iqResp.Type = "error" iqResp.Type = "error"
iqResp.From = clientroot.Session.BindJid
stanza_err := new(stanza.Err) stanza_err := new(stanza.Err)
stanza_err.Type = stanza.ErrorTypeCancel stanza_err.Type = stanza.ErrorTypeCancel
@@ -283,6 +279,7 @@ func main() {
} }
originator := JidMustParse(m.From).Bare() originator := JidMustParse(m.From).Bare()
glib.IdleAdd(func() { glib.IdleAdd(func() {
mStatus.SetText(originator) mStatus.SetText(originator)
}) })
@@ -345,6 +342,28 @@ func main() {
return 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() { glib.IdleAdd(func() {
b := gtk.NewBox(gtk.OrientationVertical, 0) b := gtk.NewBox(gtk.OrientationVertical, 0)
@@ -363,7 +382,7 @@ func main() {
fmt.Println("Got message when the tab does not exist!") 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) ba, converted_successfully := untyped_box.(*gtk.Box)
if valid && converted_successfully { if valid && converted_successfully {
@@ -505,11 +524,18 @@ func main() {
// client = c // client = c
// clientroot = c // clientroot = c
// Ping
go func() { go func() {
for { for {
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
go func() { go func() {
// Goroutine counter
goroutines := runtime.NumGoroutine()
glib.IdleAdd(func() {
gStatus.SetText(fmt.Sprintf("%d goroutines", goroutines))
})
}()
go func() {
// Ping
pingStatus.AddCSSClass("pending") pingStatus.AddCSSClass("pending")
before := time.Now() before := time.Now()
iq := new(stanza.IQ) iq := new(stanza.IQ)
@@ -971,10 +997,12 @@ func activate(app *gtk.Application) {
jid_box := gtk.NewBox(gtk.OrientationHorizontal, 10) jid_box := gtk.NewBox(gtk.OrientationHorizontal, 10)
nick_box := gtk.NewBox(gtk.OrientationHorizontal, 10) nick_box := gtk.NewBox(gtk.OrientationHorizontal, 10)
disco_box := gtk.NewBox(gtk.OrientationHorizontal, 10) disco_box := gtk.NewBox(gtk.OrientationHorizontal, 10)
bookmark_box := gtk.NewBox(gtk.OrientationHorizontal, 10)
jid_entry := gtk.NewEntry() jid_entry := gtk.NewEntry()
nick_entry := gtk.NewEntry() nick_entry := gtk.NewEntry()
disco_check := gtk.NewCheckButton() disco_check := gtk.NewCheckButton()
bookmark_check := gtk.NewCheckButton()
jid_entry.SetHAlign(gtk.AlignEnd) jid_entry.SetHAlign(gtk.AlignEnd)
jid_entry.SetHExpand(true) jid_entry.SetHExpand(true)
@@ -1004,9 +1032,14 @@ func activate(app *gtk.Application) {
disco_box.Append(disco_check) disco_box.Append(disco_check)
disco_box.SetTooltipText(loadedLocale["joinMUCDiscoCheckTooltip"]) 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(jid_box)
box.Append(nick_box) box.Append(nick_box)
box.Append(disco_box) box.Append(disco_box)
box.Append(bookmark_box)
btn := gtk.NewButtonWithLabel(loadedLocale["submit"]) btn := gtk.NewButtonWithLabel(loadedLocale["submit"])
btn.SetVAlign(gtk.AlignBaseline) btn.SetVAlign(gtk.AlignBaseline)
@@ -1035,15 +1068,7 @@ func activate(app *gtk.Application) {
im.SetPixelSize(40) im.SetPixelSize(40)
go getAvatar(t, t, im) 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) b := gtk.NewLabel(n)
box.Append(im) box.Append(im)
@@ -1065,6 +1090,13 @@ func activate(app *gtk.Application) {
box.AddController(gesture2) box.AddController(gesture2)
menu.Append(box) menu.Append(box)
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal)) 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 { if !ok {
@@ -1092,111 +1124,116 @@ func activate(app *gtk.Application) {
myIQ.Payload = &stanza.DiscoInfo{} myIQ.Payload = &stanza.DiscoInfo{}
ctx := context.TODO() ctx := context.Background()
mychan, err := client.SendIQ(ctx, myIQ) mychan, err := client.SendIQ(ctx, myIQ)
if err == nil { if err == nil {
result := <-mychan result := <-mychan
res, ok = result.Payload.(*stanza.DiscoInfo) res, ok = result.Payload.(*stanza.DiscoInfo)
if ok { if ok {
features := res.Features if len(res.Identity) >= 1 {
allowed = false features := res.Features
password_protected := false allowed = false
password := "" password_protected := false
warning_win := gtk.NewWindow() password := ""
warning_win.SetTitle(fmt.Sprintf("%s%s", loadedLocale["joinPreviewTitle"], res.Identity[0].Name)) warning_win := gtk.NewWindow()
warning_win.SetDefaultSize(400, 1) warning_win.SetTitle(fmt.Sprintf("%s%s", loadedLocale["joinPreviewTitle"], res.Identity[0].Name))
warning_win.SetResizable(false) warning_win.SetDefaultSize(400, 1)
warning_win.SetResizable(false)
buttons := gtk.NewBox(gtk.OrientationHorizontal, 10) buttons := gtk.NewBox(gtk.OrientationHorizontal, 10)
join_button := gtk.NewButtonWithLabel("Join") join_button := gtk.NewButtonWithLabel("Join")
join_button.ConnectClicked(func() { join_button.ConnectClicked(func() {
warning_win.SetVisible(false) warning_win.SetVisible(false)
if password_protected { if password_protected {
allowed = false allowed = false
password_win := gtk.NewWindow() password_win := gtk.NewWindow()
password_win.SetTitle(loadedLocale["joinPasswordRequired"]) password_win.SetTitle(loadedLocale["joinPasswordRequired"])
password_win.SetDefaultSize(400, 1) password_win.SetDefaultSize(400, 1)
password_win.SetResizable(false) password_win.SetResizable(false)
box := gtk.NewBox(gtk.OrientationVertical, 10) box := gtk.NewBox(gtk.OrientationVertical, 10)
en := gtk.NewPasswordEntry() en := gtk.NewPasswordEntry()
submit := gtk.NewButtonWithLabel(loadedLocale["submit"]) submit := gtk.NewButtonWithLabel(loadedLocale["submit"])
submit.ConnectClicked(func() { submit.ConnectClicked(func() {
password = en.Text() password = en.Text()
jm(res.Identity[0].Name, password) jm(res.Identity[0].Name, password)
password_win.SetVisible(false) password_win.SetVisible(false)
}) })
box.Append(en) box.Append(en)
box.Append(submit) box.Append(submit)
password_win.SetChild(box) password_win.SetChild(box)
password_win.SetVisible(true) password_win.SetVisible(true)
}
jm(res.Identity[0].Name, password)
})
cancel_button := gtk.NewButtonWithLabel(loadedLocale["cancel"])
cancel_button.ConnectClicked(func() {
warning_win.SetVisible(false)
})
join_button.SetHExpand(true)
cancel_button.SetHExpand(true)
buttons.Append(join_button)
buttons.Append(cancel_button)
warning_box := gtk.NewBox(gtk.OrientationVertical, 10)
header := gtk.NewLabel(res.Identity[0].Name)
warning_box.Append(header)
addFeature := func(icon string, description string) {
box := gtk.NewBox(gtk.OrientationHorizontal, 10)
box.Append(gtk.NewImageFromPaintable(clientAssetsLoad(icon)))
box.Append(gtk.NewLabel(description))
warning_box.Append(box)
} }
jm(res.Identity[0].Name, password) for _, feature := range features {
}) switch feature.Var {
case "muc_passwordprotected":
cancel_button := gtk.NewButtonWithLabel(loadedLocale["cancel"]) password_protected = true
cancel_button.ConnectClicked(func() { addFeature("muc_passwordprotected", loadedLocale["muc_passwordprotected_description"])
warning_win.SetVisible(false) case "muc_unsecured":
}) addFeature("muc_unsecured", loadedLocale["muc_unsecured_description"])
case "muc_membersonly":
join_button.SetHExpand(true) addFeature("muc_membersonly", loadedLocale["muc_membersonly_description"])
cancel_button.SetHExpand(true) case "muc_open":
addFeature("muc_open", loadedLocale["muc_open_description"])
buttons.Append(join_button) case "muc_moderated":
buttons.Append(cancel_button) addFeature("muc_moderated", loadedLocale["muc_moderated_description"])
warning_box := gtk.NewBox(gtk.OrientationVertical, 10) case "muc_unmoderated":
header := gtk.NewLabel(res.Identity[0].Name) addFeature("muc_unmoderated", loadedLocale["muc_unmoderated_description"])
warning_box.Append(header) case "muc_nonanonymous":
addFeature := func(icon string, description string) { addFeature("muc_nonanonymous", loadedLocale["muc_nonanonymous_description"])
box := gtk.NewBox(gtk.OrientationHorizontal, 10) case "muc_semianonymous":
box.Append(gtk.NewImageFromPaintable(clientAssetsLoad(icon))) addFeature("muc_semianonymous", loadedLocale["muc_semianonymous_description"])
box.Append(gtk.NewLabel(description)) case "muc_persistent":
warning_box.Append(box) addFeature("muc_persistent", loadedLocale["muc_persistent_description"])
} case "muc_temporary":
addFeature("muc_temporary", loadedLocale["muc_temporary_description"])
for _, feature := range features { case "muc_public":
switch feature.Var { addFeature("muc_public", loadedLocale["muc_public_description"])
case "muc_passwordprotected": case "muc_hidden":
password_protected = true addFeature("muc_hidden", loadedLocale["muc_hidden_description"])
addFeature("muc_passwordprotected", loadedLocale["muc_passwordprotected_description"]) case "urn:xmpp:mam:0":
case "muc_unsecured": addFeature("ok", loadedLocale["urn:xmpp:mam_description"])
addFeature("muc_unsecured", loadedLocale["muc_unsecured_description"]) case "urn:xmpp:message-moderate:0":
case "muc_membersonly": addFeature("moderate", loadedLocale["urn:xmpp:message-moderate_description"])
addFeature("muc_membersonly", loadedLocale["muc_membersonly_description"]) /*
case "muc_open": default:
addFeature("muc_open", loadedLocale["muc_open_description"]) addFeature("comment", feature.Var)
case "muc_moderated": */
addFeature("muc_moderated", loadedLocale["muc_moderated_description"]) }
case "muc_unmoderated":
addFeature("muc_unmoderated", loadedLocale["muc_unmoderated_description"])
case "muc_nonanonymous":
addFeature("muc_nonanonymous", loadedLocale["muc_nonanonymous_description"])
case "muc_semianonymous":
addFeature("muc_semianonymous", loadedLocale["muc_semianonymous_description"])
case "muc_persistent":
addFeature("muc_persistent", loadedLocale["muc_persistent_description"])
case "muc_temporary":
addFeature("muc_temporary", loadedLocale["muc_temporary_description"])
case "muc_public":
addFeature("muc_public", loadedLocale["muc_public_description"])
case "muc_hidden":
addFeature("muc_hidden", loadedLocale["muc_hidden_description"])
case "urn:xmpp:mam:0":
addFeature("ok", loadedLocale["urn:xmpp:mam_description"])
case "urn:xmpp:message-moderate:0":
addFeature("moderate", loadedLocale["urn:xmpp:message-moderate_description"])
/*
default:
addFeature("comment", feature.Var)
*/
} }
}
warning_box.Append(buttons) warning_box.Append(buttons)
warning_win.SetChild(warning_box) warning_win.SetChild(warning_box)
warning_win.Present() warning_win.Present()
} else {
allowed = false
showErrorDialog(fmt.Errorf(loadedLocale["discoFail"]), win)
}
} else { } else {
allowed = false allowed = false
if result.Error != nil { if result.Error != nil {
@@ -1274,9 +1311,16 @@ func activate(app *gtk.Application) {
mStatus = gtk.NewLabel("-") mStatus = gtk.NewLabel("-")
mStatus.AddController(gesture1) mStatus.AddController(gesture1)
gIcon = gtk.NewImageFromPaintable((clientAssetsLoad("timeline_marker")))
gIcon.AddCSSClass("icon")
gStatus = gtk.NewLabel("...")
cBox.Append(mIcon) cBox.Append(mIcon)
cBox.Append(mStatus) cBox.Append(mStatus)
cBox.Append(gIcon)
cBox.Append(gStatus)
statBar.Append(mBox) statBar.Append(mBox)
pBox := gtk.NewBox(gtk.OrientationHorizontal, 0) pBox := gtk.NewBox(gtk.OrientationHorizontal, 0)
+14
View File
@@ -112,3 +112,17 @@
text-decoration: underline; text-decoration: underline;
color: green; 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;
}
+13 -7
View File
@@ -7,9 +7,15 @@ import (
"sync" "sync"
) )
type abMessage struct {
label_ref *gtk.Label
ocu_id string
}
type chatTab struct { type chatTab struct {
isMuc bool isMuc bool
msgs *gtk.ListBox msgs *gtk.ListBox
msg_refsID map[string]*abMessage
name string name string
current_nick string current_nick string
muc_presence *stanza.Presence muc_presence *stanza.Presence
@@ -18,17 +24,17 @@ type chatTab struct {
type BlockingMode int type BlockingMode int
const ( const (
Drop BlockingMode = iota // Do not even process if the entity is blocked Drop BlockingMode = iota // Do not even process if the entity is blocked
Hide // Hide the message but allow the user to expand it if they wish (discord style) Hide // Hide the message but allow the user to expand it if they wish (discord style)
Highlight // Just highlight the message in orange Highlight // Just highlight the message in orange
) )
type DiscoveryMode int type DiscoveryMode int
const ( const (
Everyone DiscoveryMode = iota // All entities can query Everyone DiscoveryMode = iota // All entities can query
OnlyRoster // Only people on your roster can query OnlyRoster // Only people on your roster can query
None // Nobody can query None // Nobody can query
) )
type lambdaConfig struct { type lambdaConfig struct {
@@ -60,7 +66,7 @@ type lambdaConfig struct {
RandomizeResource bool // If this is set to true, then the resource will be completely randomized by the server on every single connect RandomizeResource bool // If this is set to true, then the resource will be completely randomized by the server on every single connect
// Privacy settings // Privacy settings
DiscoPrivacy DiscoveryMode // Whether or not Lambda will report its service discovery features and Identity. Reccomended mode is Everyone, Default is Everyone DiscoPrivacy DiscoveryMode // Whether or not Lambda will report its service discovery features and Identity. Reccomended mode is Everyone, Default is Everyone
VersionPrivacy DiscoveryMode // Whether or not Lambda will report its version information. Reccomended mode is Roster, Default is Everyone VersionPrivacy DiscoveryMode // Whether or not Lambda will report its version information. Reccomended mode is Roster, Default is Everyone
IgnoreInsteadOfReturnErrorUponPrivacyViolation bool // If set to true, Lambda will simply ignore Disco and Query Version requests from entities that are untrusted as per the user's discovery mode. If set to false, a service-unavailable error will be reported. IgnoreInsteadOfReturnErrorUponPrivacyViolation bool // If set to true, Lambda will simply ignore Disco and Query Version requests from entities that are untrusted as per the user's discovery mode. If set to false, a service-unavailable error will be reported.
+1 -1
View File
@@ -1,3 +1,3 @@
package main package main
var lambda_version string = "7" var lambda_version string = "8"
+33
View File
@@ -2,6 +2,7 @@ package main
import ( import (
"encoding/xml" "encoding/xml"
"fmt"
"gosrc.io/xmpp/stanza" "gosrc.io/xmpp/stanza"
) )
@@ -17,6 +18,38 @@ type Bookmark struct {
Extensions []any `xml:"extensions,omitempty"` 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() { func init() {
stanza.TypeRegistry.MapExtension(stanza.PKTIQ, xml.Name{Space: "urn:xmpp:bookmarks:1", Local: "conference"}, Bookmark{}) stanza.TypeRegistry.MapExtension(stanza.PKTIQ, xml.Name{Space: "urn:xmpp:bookmarks:1", Local: "conference"}, Bookmark{})
} }
+20
View File
@@ -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{})
}
+60
View File
@@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"fmt" "fmt"
"gosrc.io/xmpp" "gosrc.io/xmpp"
"gosrc.io/xmpp/stanza" "gosrc.io/xmpp/stanza"
@@ -140,3 +141,62 @@ func sendVoiceRequest(c xmpp.Sender, sendTo string) error {
} }
return nil 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
}