From 09a809c102befafc155d0911ac8f146384c6a1ff Mon Sep 17 00:00:00 2001 From: sunglocto Date: Sun, 15 Feb 2026 13:08:52 +0000 Subject: [PATCH] add Destroy room button, show error notification on presence error and show disabled lambda icon when not focused on any chat --- assets/group.png | Bin 0 -> 753 bytes assets/lambda-disabled.png | Bin 0 -> 16079 bytes assets/vcard.png | Bin 0 -> 362 bytes go.mod | 11 +++++++ go.sum | 34 +++++++++++++++++++++ gtk-helpers.go | 33 +++++---------------- gtk-message.go | 13 +++++++- main.go | 59 +++++++++++++++++++++++++++++++++++-- style.css | 4 +++ 9 files changed, 125 insertions(+), 29 deletions(-) create mode 100644 assets/group.png create mode 100644 assets/lambda-disabled.png create mode 100644 assets/vcard.png diff --git a/assets/group.png b/assets/group.png new file mode 100644 index 0000000000000000000000000000000000000000..7fb4e1f1e1cd6ee67d33ffd24f09ddd5c3478bec GIT binary patch literal 753 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7SkfJR9T^zbpD<_bdda}R zAX(xXQ4*Y=R#Ki=l*-_klAn~S;F+74o*I;zm{M7IGS!BGfvMTk#WBRbgLNMP*&Hsv~Uj`=TRX z*)Xl2x-DtaWOj&}(D=4ZqrsT-qY+yleBmSVqY?J}ZxhZTncd zP5j_dyEVEN0upKgbE_}P2~ODb=*Zbe-r6pF+$nO^dne2{@C-Ro$MS}&=GFf00}X7- zy5(nq$MJ1 z6K6Mc`oI5a;gT!evnu7FK`D1>o@$A(>JHmLmaDgwI!@YDoc!{iKWzEqLndpToL4j^ zzEYdzq$xi|@$>}N|BJQj8}~k+9ikTcaofR1l}{(!*i^VTx`D}y!P8w$?}en@(k-h_ zWeai~K3*+xcM?x)b?Fb|g7-URXO(ez9qKy%`2Io@-NbsY?WS!vrDR{OUYs#UOwQkK zhuH>+mV3-k`k8kgc6g?6U^zpQh(MN2NAmRvf{m87kItWrQx?%@64=QwF`3yZi`gby zATv$jti+Mv)2BZq2r|YCU%nq5%+*-NbLo1+kI)s3%qJunHq~!m@zrVd4tY5pr4I`i zD;$lS8#wdKW=kP&wF8&VwHonHs}eioW&UFN{GUBfCw)km*bwhnzlmYO_8Lb91_lOC LS3j3^P645zQ%?_ywJ;4JWnEM{QfI}E~%$MaXD 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 literal 0 HcmV?d00001 diff --git a/assets/vcard.png b/assets/vcard.png new file mode 100644 index 0000000000000000000000000000000000000000..c68dc819918a53acde41f23229443d387a063b95 GIT binary patch literal 362 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7SkfJR9T^xl_SO6joXo($ zsOah97-Dhy=;V!F%#I?i=WpL_5m6HBJ}Dj%@q?XPdV{a}iC_F;{~8W2+a{o+`^IR3 zz!4sfCV_%1T^4QWXm0NP2|+#{HzIjkIQVSRmQ_5zS3Xnlxy)>x!gGnC<+)yAeyk4j z&J|CetL5=|D??c6$x|yU94uSe8`)NCN6vej8pq1>tErCVNcctOT7H+$zbCT4Fr2}8 zqmJQ$s}|S(-5mj4mA~V;m+<-=H-jClwoEEavm`e6hu&^%{w^x1!t_yW z19wRSUsx@xWDMt#1@HgdIl8fYaXXWVL0bMrp4>H6d@?m&wr`i1hUe-_O>ZcC@E~g1 zXa3elDr`|1caO|CEOlg6_W{P2{a#;fpZ3O~RT=hyzw_|t|n Q3=9kmp00i_>zopr0C-T4$^ZZW literal 0 HcmV?d00001 diff --git a/go.mod b/go.mod index e48a11f..c2c40fb 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.25.5 require ( github.com/BurntSushi/toml v1.6.0 github.com/diamondburned/gotk4/pkg v0.3.1 + github.com/gen2brain/beeep v0.11.2 github.com/google/uuid v1.1.1 github.com/jacoblockett/sanitizefilename v1.0.1 github.com/jasonlovesdoggo/gopen v0.0.0-20250130105607-39c98c645030 @@ -15,11 +16,21 @@ require ( ) require ( + git.sr.ht/~jackmordaunt/go-toast v1.1.2 // indirect github.com/KarpelesLab/weak v0.1.1 // indirect + github.com/esiqveland/notify v0.13.3 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/jackmordaunt/icns/v3 v3.0.1 // indirect github.com/kr/text v0.1.0 // indirect + github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect + github.com/sergeymakinen/go-bmp v1.0.0 // indirect + github.com/sergeymakinen/go-ico v1.0.0-beta.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/net v0.29.0 // indirect golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.30.0 // indirect golang.org/x/text v0.18.0 // indirect golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 // indirect mellium.im/reader v0.1.0 // indirect diff --git a/go.sum b/go.sum index ab080ae..8f16728 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +git.sr.ht/~jackmordaunt/go-toast v1.1.2 h1:/yrfI55LRt1M7H1vkaw+NaH1+L1CDxrqDltwm5euVuE= +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= @@ -10,18 +12,27 @@ github.com/chromedp/cdproto v0.0.0-20190926234355-1b4886c6fad6/go.mod h1:0YChpVz github.com/chromedp/chromedp v0.3.1-0.20190619195644-fd957a4d2901/go.mod h1:mJdvfrVn594N9tfiPecUidF6W5jPRKHymqHfzbobPsM= github.com/chromedp/chromedp v0.4.0/go.mod h1:DC3QUn4mJ24dwjcaGQLoZrhm4X/uPHZ6spDbS2uFhm4= 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/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/esiqveland/notify v0.13.3 h1:QCMw6o1n+6rl+oLUfg8P1IIDSFsDEb2WlXvVvIJbI/o= +github.com/esiqveland/notify v0.13.3/go.mod h1:hesw/IRYTO0x99u1JPweAl4+5mwXJibQVUcP0Iu5ORE= github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +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-interpreter/wagon v0.5.1-0.20190713202023-55a163980b6c/go.mod h1:5+b/MBYkclRZngKF5s6qrgWxSLgE9F5dFdO1hAueZLc= github.com/go-interpreter/wagon v0.6.0/go.mod h1:5+b/MBYkclRZngKF5s6qrgWxSLgE9F5dFdO1hAueZLc= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -33,6 +44,8 @@ github.com/google/pprof v0.0.0-20190908185732-236ed259b199/go.mod h1:zfwlbNMJ+OI github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jackmordaunt/icns/v3 v3.0.1 h1:xxot6aNuGrU+lNgxz5I5H0qSeCjNKp8uTXB1j8D4S3o= +github.com/jackmordaunt/icns/v3 v3.0.1/go.mod h1:5sHL59nqTd2ynTnowxB/MDQFhKNqkK8X687uKNygaSQ= github.com/jacoblockett/sanitizefilename v1.0.1 h1:HhPMoPp05U5aKjhht+d7lsqhyF4trKSBme0FE6S/1C4= github.com/jacoblockett/sanitizefilename v1.0.1/go.mod h1:/cQHSz2fHeR1iDKpHTSW/MIyONa+Uqj0eszbvPuIxNs= github.com/jasonlovesdoggo/gopen v0.0.0-20250130105607-39c98c645030 h1:NFCJG3BerP/5ZLXwu08x9xDs+9p7AYFMeo5IXjGANxw= @@ -58,21 +71,36 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +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/sergeymakinen/go-bmp v1.0.0 h1:SdGTzp9WvCV0A1V0mBeaS7kQAwNLdVJbmHlqNWq0R+M= +github.com/sergeymakinen/go-bmp v1.0.0/go.mod h1:/mxlAQZRLxSvJFNIEGGLBE/m40f3ZnUifpgVDlcUIEY= +github.com/sergeymakinen/go-ico v1.0.0-beta.0 h1:m5qKH7uPKLdrygMWxbamVn+tl2HfiA3K6MFJw4GfZvQ= +github.com/sergeymakinen/go-ico v1.0.0-beta.0/go.mod h1:wQ47mTczswBO5F0NoDt7O0IXgnV4Xy3ojrroMQzyhUk= github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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/twitchyliquid64/golang-asm v0.0.0-20190126203739-365674df15fc/go.mod h1:NoCfSFWosfqMqmmD7hApkirIK9ozpHjxRnRxs1l413A= go.coder.com/go-tools v0.0.0-20190317003359-0c6a35b74a16/go.mod h1:iKV5yK9t+J5nG9O3uF6KYdPEz3dyfMyB15MN1rbQ8Qw= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= @@ -108,6 +136,9 @@ golang.org/x/sys v0.0.0-20190618155005-516e3c20635f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190927073244-c990c680b611/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= @@ -127,6 +158,9 @@ gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKW gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gosrc.io/xmpp v0.5.1 h1:Rgrm5s2rt+npGggJH3HakQxQXR8ZZz3+QRzakRQqaq4= gosrc.io/xmpp v0.5.1/go.mod h1:L3NFMqYOxyLz3JGmgFyWf7r9htE91zVGiK40oW4RwdY= gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= diff --git a/gtk-helpers.go b/gtk-helpers.go index ff3ae8d..8f50834 100644 --- a/gtk-helpers.go +++ b/gtk-helpers.go @@ -50,6 +50,7 @@ func switchToTab(jid string, w *gtk.Window) { scroller.SetChild(typed_tab.msgs) if typed_tab.isMuc { + m, ok := mucmembers.Load(jid) if !ok { return @@ -61,7 +62,9 @@ func switchToTab(jid string, w *gtk.Window) { mm := ma.Members gen := gtk.NewBox(gtk.OrientationVertical, 0) + i := 0 mm.Range(func(k, v any) bool { + i++ userbox := gtk.NewBox(gtk.OrientationHorizontal, 0) u := v.(stanza.Presence) @@ -76,36 +79,13 @@ func switchToTab(jid string, w *gtk.Window) { nick_label := gtk.NewLabel(JidMustParse(u.From).Resource) nick_label.SetEllipsize(pango.EllipsizeEnd) - /* - affil_label := gtk.NewLabel("") - switch mu.MucUserItem.Affiliation { - case "owner": - affil_label.SetText("O") - case "admin": - affil_label.SetText("A") - case "member": - affil_label.SetText("M") - case "none": - affil_label.SetText("-") - } - */ - nick_label.AddCSSClass(mu.MucUserItem.Role) if mu.MucUserItem.Role == "visitor" { nick_label.SetOpacity(0.5) } - /* - affil_label.SetHAlign(gtk.AlignEnd) - affil_label.SetHExpand(true) - - - affil_label.AddCSSClass(mu.MucUserItem.Affiliation) - */ - userbox.SetTooltipText(fmt.Sprintf("%s\n%s\n%s\nRight-click for more information", u.From, mu.MucUserItem.Role, mu.MucUserItem.Affiliation)) userbox.Append(nick_label) - // userbox.Append(affil_label) var hats Hats ok := u.Get(&hats) @@ -113,8 +93,6 @@ func switchToTab(jid string, w *gtk.Window) { for _, hat := range hats.Hats { tag := gtk.NewImageFromPaintable(clientAssets["tag"]) tag.SetTooltipText(hat.Title) - // tag.SetHAlign(gtk.AlignEnd) - // tag.SetHExpand(true) userbox.Prepend(tag) } } @@ -274,6 +252,11 @@ func switchToTab(jid string, w *gtk.Window) { return true }) + headerBox := gtk.NewBox(gtk.OrientationHorizontal, 0) + headerBox.Append(gtk.NewImageFromPaintable(clientAssets["group"])) + headerBox.Append(gtk.NewLabel(fmt.Sprintf("%d participant(s)", i))) + gen.Prepend(headerBox) + memberList.SetChild(gen) } else { memberList.SetChild(gtk.NewLabel(jid)) diff --git a/gtk-message.go b/gtk-message.go index bb446b1..fc263a4 100644 --- a/gtk-message.go +++ b/gtk-message.go @@ -65,10 +65,11 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter { if m.Error.Type != "" { error_box := gtk.NewBox(gtk.OrientationHorizontal, 0) cancel_img := gtk.NewImageFromPaintable(clientAssets["cancel"]) - error_label := gtk.NewLabel(m.Error.Text) + error_label := gtk.NewLabel(m.Error.Text+ ": ") error_box.Append(cancel_img) error_box.Append(error_label) + error_box.Append(gtk.NewLabel(m.Error.Reason)) return error_box } @@ -148,6 +149,7 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter { al := gtk.NewLabel(jid.MustParse(m.From).Resourcepart()) al.AddCSSClass("author") + al.SetSelectable(true) if m.Type == stanza.MessageTypeGroupchat { mo, _ := mucmembers.Load(jid.MustParse(m.From).Bare().String()) @@ -215,6 +217,15 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter { authorBox.Append(mbtn) } + if m.Subject != "" { + subjectlabel := gtk.NewLabel(m.Subject) + subjectlabel.SetWrap(true) + subjectlabel.SetSelectable(true) + subjectlabel.SetHAlign(gtk.AlignFill) + subjectlabel.AddCSSClass("subject") + mainBox.Append(subjectlabel) + } + return mainBox } diff --git a/main.go b/main.go index 2aaf01d..35a2d34 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,7 @@ import ( "github.com/diamondburned/gotk4/pkg/gio/v2" "github.com/diamondburned/gotk4/pkg/glib/v2" "github.com/diamondburned/gotk4/pkg/gtk/v4" + "github.com/gen2brain/beeep" "path/filepath" "github.com/BurntSushi/toml" @@ -29,7 +30,7 @@ import ( var loadedConfig lambdaConfig -var empty_dialog *gtk.Label +var empty_dialog *gtk.Image // var msgs *gtk.ListBox var content *gtk.Widgetter @@ -89,6 +90,15 @@ var cancelB64 string = base64.StdEncoding.EncodeToString(cancelBytes) var tagBytes []byte var tagB64 string = base64.StdEncoding.EncodeToString(tagBytes) + +//go:embed assets/lambda-disabled.png +var logoDisabledBytes []byte +var logoDisabledB64 string = base64.StdEncoding.EncodeToString(logoDisabledBytes) + +//go:embed assets/group.png +var groupBytes []byte +var groupB64 string = base64.StdEncoding.EncodeToString(groupBytes) + var clientAssets map[string]gdk.Paintabler = make(map[string]gdk.Paintabler) var lockedJIDs map[string]bool = make(map[string]bool) @@ -165,6 +175,23 @@ func init() { loader.Close() clientAssets["outcast"] = gdk.NewTextureForPixbuf(loader.Pixbuf()) + + + loader = gdkpixbuf.NewPixbufLoader() + + disabledLogoData, _ := base64.StdEncoding.DecodeString(logoDisabledB64) + loader.Write(disabledLogoData) + loader.Close() + + clientAssets["disabled_logo"] = gdk.NewTextureForPixbuf(loader.Pixbuf()) + + loader = gdkpixbuf.NewPixbufLoader() + + groupData, _ := base64.StdEncoding.DecodeString(groupB64) + loader.Write(groupData) + loader.Close() + + clientAssets["group"] = gdk.NewTextureForPixbuf(loader.Pixbuf()) } func main() { @@ -307,7 +334,8 @@ func main() { return } - if presence.Error != *new(stanza.Err) { + if presence.Error.Reason != "" { + beeep.Notify(fmt.Sprintf("%s : %s", presence.From, presence.Error.Reason), presence.Error.Text, cancelBytes) return } @@ -468,6 +496,7 @@ func activate(app *gtk.Application) { fileMenu := gio.NewMenu() fileMenu.Append("Join MUC", "app.join") fileMenu.Append("Start DM", "app.dm") + fileMenu.Append("Destroy MUC", "app.destroymuc") helpMenu := gio.NewMenu() helpMenu.Append("About", "app.about") @@ -478,6 +507,28 @@ func activate(app *gtk.Application) { a.SetVisible(true) }) + destroymucAction := gio.NewSimpleAction("destroymuc", nil) + destroymucAction.ConnectActivate(func(p *glib.Variant) { + cur, ok := tabs.Load(current) + if ok { + cur := cur.(*chatTab) + if cur.isMuc { + client.SendRaw(fmt.Sprintf(` + + + + User requested + + + + `, clientroot.Session.BindJid, current, JidMustParse(clientroot.Session.BindJid).Bare())) + } + } + }) + joinAction := gio.NewSimpleAction("join", nil) joinAction.ConnectActivate(func(p *glib.Variant) { box := gtk.NewBox(gtk.OrientationVertical, 0) @@ -540,6 +591,7 @@ func activate(app *gtk.Application) { app.AddAction(joinAction) app.AddAction(aboutAction) + app.AddAction(destroymucAction) the_menu.AppendSubmenu("File", fileMenu) the_menu.AppendSubmenu("Help", helpMenu) @@ -552,7 +604,8 @@ func activate(app *gtk.Application) { window.Window.SetDefaultSize(500, 500) menu = gtk.NewBox(gtk.OrientationVertical, 0) - empty_dialog = gtk.NewLabel("You are not focused on any chats.") + empty_dialog = gtk.NewImageFromPaintable(clientAssets["disabled_logo"]) + empty_dialog.SetPixelSize(100) empty_dialog.SetVExpand(true) scroller = gtk.NewScrolledWindow() diff --git a/style.css b/style.css index c0c4475..39db015 100644 --- a/style.css +++ b/style.css @@ -39,3 +39,7 @@ color: black; font-family: monospace; } + +.subject { + color: lime; +}