19 Commits
Author SHA1 Message Date
Sunglocto 23288e3dfa minor spelling mistake (world implodes) 2026-08-23 20:36:42 +01:00
Sunglocto 6d95c8419c add hiatus note 2026-08-23 20:35:28 +01:00
Sunglocto a31d9e766d Add april fools joke 2026-03-31 07:39:06 +01:00
Sunglocto 542ade77b2 Modify corrected message appearance and make notification text less insane 2026-01-25 16:45:42 +00:00
Sunglocto 183ec02918 set notification title to pi 2026-01-13 16:59:32 +00:00
Sunglocto 881b72cb15 Add experimental stanza sender and allow sending empty messages upon confirmation 2026-01-12 16:36:05 +00:00
Sunglocto 4d0e29550c Use better notification lib 2026-01-11 09:12:13 +00:00
Sunglocto b926173f43 Merge branch 'master' of https://forge.sunglocto.net/sunglocto/pi-im 2026-01-11 08:54:27 +00:00
Sunglocto 2667b0ccfd Colored nicks 2026-01-11 08:54:13 +00:00
Sunglocto 3aa8054dc0 Fix AUR link (oof that's embarassing, it's been like that for months) 2026-01-10 15:16:48 +00:00
Sunglocto ad9a0ea9a8 fix app icon 2026-01-10 14:56:28 +00:00
Sunglocto de40a5dec8 changes to follow 7bab52f033 2026-01-10 14:44:27 +00:00
Sunglocto 78c7f0175d changes to follow 7bab52f033 2026-01-10 14:43:57 +00:00
Sunglocto 7bab52f033 Remove loading gif garbage 2026-01-10 14:42:06 +00:00
Sunglocto 652fd3ea19 sending retractions 2026-01-10 14:38:58 +00:00
Sunglocto 536ce4cae6 indicator when user is on note to self 2026-01-10 14:02:18 +00:00
Sunglocto 202e3ba6b1 Format code 2026-01-06 07:08:15 +00:00
Sunglocto 7f01f38436 Bump version number 2026-01-06 05:48:42 +00:00
Sunglocto 4afe2de35d fix some timeline glitching 2026-01-05 13:57:12 +00:00
5 changed files with 235 additions and 95 deletions
+9 -1
View File
@@ -1,3 +1,11 @@
# Notice
Pi is on hiatus for the time being. The reason why being that the libraries that Pi uses, being the Oasis SDK and the Mellium libraries, have multiple fundamental issues and bugs that are unlikely to be fixed. In addition, I began writing this project with a much less consolidated knowledge of Go and programming in general, meaning there are core architectural issues with this project. Regardless, you are still free to use Pi, and I may even rewrite the project to add some new features. Who knows.
I mostly work on [Lambda](https://forge.sunglocto.net/sunglocto/lambda) these days, which has already surpassed Pi in terms of features and usability.
<hr/>
<center> <center>
<img width="100" height="100" src="https://forge.sunglocto.net/sunglocto/pi-im/raw/branch/master/pi.png"> <img width="100" height="100" src="https://forge.sunglocto.net/sunglocto/pi-im/raw/branch/master/pi.png">
</center> </center>
@@ -112,7 +120,7 @@ go build -tags wayland .
## εγκατάσταση ## εγκατάσταση
(installation) (installation)
pi currently has no consolidated way of installing it. There is an [Arch User Repository package available](https://aur.archlinux.org/pi-im), which is maintained by [snit](https://isekai.rocks/~snit). pi currently has no consolidated way of installing it. There is an [Arch User Repository package available](https://aur.archlinux.org/packages/pi-im), which is maintained by [snit](https://isekai.rocks/~snit).
## υποστήριξη ## υποστήριξη
(support) (support)
+9 -1
View File
@@ -4,7 +4,8 @@ go 1.25.1
require ( require (
fyne.io/fyne/v2 v2.7.1 fyne.io/fyne/v2 v2.7.1
fyne.io/x/fyne v0.0.0-20250910205345-ecc79984d005 fyne.io/x/fyne v0.0.0-20251214153509-fa68a7d234d5
github.com/gen2brain/beeep v0.11.2
github.com/makeworld-the-better-one/go-isemoji v1.3.0 github.com/makeworld-the-better-one/go-isemoji v1.3.0
github.com/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d github.com/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d
github.com/shreve/musicwand v0.0.1 github.com/shreve/musicwand v0.0.1
@@ -14,8 +15,10 @@ require (
require ( require (
fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58 // indirect fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58 // indirect
git.sr.ht/~jackmordaunt/go-toast v1.1.2 // indirect
github.com/BurntSushi/toml v1.5.0 // indirect github.com/BurntSushi/toml v1.5.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/esiqveland/notify v0.13.3 // indirect
github.com/fredbi/uri v1.1.1 // indirect github.com/fredbi/uri v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fyne-io/gl-js v0.2.0 // indirect github.com/fyne-io/gl-js v0.2.0 // indirect
@@ -24,20 +27,25 @@ require (
github.com/fyne-io/oksvg v0.2.0 // indirect github.com/fyne-io/oksvg v0.2.0 // indirect
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-text/render v0.2.0 // indirect github.com/go-text/render v0.2.0 // indirect
github.com/go-text/typesetting v0.2.1 // indirect github.com/go-text/typesetting v0.2.1 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/hack-pad/go-indexeddb v0.3.2 // indirect github.com/hack-pad/go-indexeddb v0.3.2 // indirect
github.com/hack-pad/safejs v0.1.0 // indirect github.com/hack-pad/safejs v0.1.0 // indirect
github.com/jackmordaunt/icns/v3 v3.0.1 // indirect
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade // indirect github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade // indirect
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/nicksnyder/go-i18n/v2 v2.5.1 // indirect github.com/nicksnyder/go-i18n/v2 v2.5.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rymdport/portal v0.4.2 // indirect github.com/rymdport/portal v0.4.2 // indirect
github.com/sergeymakinen/go-bmp v1.0.0 // indirect
github.com/sergeymakinen/go-ico v1.0.0-beta.0 // indirect
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect
github.com/stretchr/testify v1.11.1 // indirect github.com/stretchr/testify v1.11.1 // indirect
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect
github.com/yuin/goldmark v1.7.8 // indirect github.com/yuin/goldmark v1.7.8 // indirect
golang.org/x/crypto v0.36.0 // indirect golang.org/x/crypto v0.36.0 // indirect
golang.org/x/image v0.24.0 // indirect golang.org/x/image v0.24.0 // indirect
+24 -16
View File
@@ -2,8 +2,10 @@ fyne.io/fyne/v2 v2.7.1 h1:ja7rNHWWEooha4XBIZNnPP8tVFwmTfwMJdpZmLxm2Zc=
fyne.io/fyne/v2 v2.7.1/go.mod h1:xClVlrhxl7D+LT+BWYmcrW4Nf+dJTvkhnPgji7spAwE= fyne.io/fyne/v2 v2.7.1/go.mod h1:xClVlrhxl7D+LT+BWYmcrW4Nf+dJTvkhnPgji7spAwE=
fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58 h1:eA5/u2XRd8OUkoMqEv3IBlFYSruNlXD8bRHDiqm0VNI= fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58 h1:eA5/u2XRd8OUkoMqEv3IBlFYSruNlXD8bRHDiqm0VNI=
fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs= fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs=
fyne.io/x/fyne v0.0.0-20250910205345-ecc79984d005 h1:CmdApAnt07juL0dhcFReFGpADUdRjjm0eDVJDS01uKE= fyne.io/x/fyne v0.0.0-20251214153509-fa68a7d234d5 h1:kDuBckHtdKTNV+jq0AornXroGSd/GMq06dBNXOWfmyY=
fyne.io/x/fyne v0.0.0-20250910205345-ecc79984d005/go.mod h1:kQFmF5meMIXnyCioLoCrXol5opruSS/PHYGKMBIE3SU= fyne.io/x/fyne v0.0.0-20251214153509-fa68a7d234d5/go.mod h1:kQFmF5meMIXnyCioLoCrXol5opruSS/PHYGKMBIE3SU=
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 v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
@@ -11,6 +13,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
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/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/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
github.com/fredbi/uri v1.1.1 h1:xZHJC08GZNIUhbP5ImTHnt5Ya0T8FI2VAwI/37kh2Ko= github.com/fredbi/uri v1.1.1 h1:xZHJC08GZNIUhbP5ImTHnt5Ya0T8FI2VAwI/37kh2Ko=
@@ -25,10 +29,14 @@ github.com/fyne-io/image v0.1.1 h1:WH0z4H7qfvNUw5l4p3bC1q70sa5+YWVt6HCj7y4VNyA=
github.com/fyne-io/image v0.1.1/go.mod h1:xrfYBh6yspc+KjkgdZU/ifUC9sPA5Iv7WYUBzQKK7JM= github.com/fyne-io/image v0.1.1/go.mod h1:xrfYBh6yspc+KjkgdZU/ifUC9sPA5Iv7WYUBzQKK7JM=
github.com/fyne-io/oksvg v0.2.0 h1:mxcGU2dx6nwjJsSA9PCYZDuoAcsZ/OuJlvg/Q9Njfo8= github.com/fyne-io/oksvg v0.2.0 h1:mxcGU2dx6nwjJsSA9PCYZDuoAcsZ/OuJlvg/Q9Njfo8=
github.com/fyne-io/oksvg v0.2.0/go.mod h1:dJ9oEkPiWhnTFNCmRgEze+YNprJF7YRbpjgpWS4kzoI= github.com/fyne-io/oksvg v0.2.0/go.mod h1:dJ9oEkPiWhnTFNCmRgEze+YNprJF7YRbpjgpWS4kzoI=
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-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA= github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA=
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw= github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
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/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc= github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc=
github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU= github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU=
github.com/go-text/typesetting v0.2.1 h1:x0jMOGyO3d1qFAPI0j4GSsh7M0Q3Ypjzr4+CEVg82V8= github.com/go-text/typesetting v0.2.1 h1:x0jMOGyO3d1qFAPI0j4GSsh7M0Q3Ypjzr4+CEVg82V8=
@@ -44,6 +52,8 @@ github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQb
github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0= github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0=
github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8= github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8=
github.com/hack-pad/safejs v0.1.0/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio= github.com/hack-pad/safejs v0.1.0/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio=
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/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade h1:FmusiCI1wHw+XQbvL9M+1r/C3SPqKrmBaIOYwVfQoDE= github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade h1:FmusiCI1wHw+XQbvL9M+1r/C3SPqKrmBaIOYwVfQoDE=
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o= github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o=
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M= github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M=
@@ -67,6 +77,10 @@ github.com/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d/go.mod h1:TbpErk
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/rymdport/portal v0.4.2 h1:7jKRSemwlTyVHHrTGgQg7gmNPJs88xkbKcIL3NlcmSU= github.com/rymdport/portal v0.4.2 h1:7jKRSemwlTyVHHrTGgQg7gmNPJs88xkbKcIL3NlcmSU=
github.com/rymdport/portal v0.4.2/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4= github.com/rymdport/portal v0.4.2/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4=
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/shreve/musicwand v0.0.1 h1:uF1GDmk6b9xZPAGJU3iWBSqKruyVeyVs/cqM6YzaJ3k= github.com/shreve/musicwand v0.0.1 h1:uF1GDmk6b9xZPAGJU3iWBSqKruyVeyVs/cqM6YzaJ3k=
github.com/shreve/musicwand v0.0.1/go.mod h1:y7oBkMLTfGmpIxoKQFwXlzWLtffcQIpX/1no+iNPxwQ= github.com/shreve/musicwand v0.0.1/go.mod h1:y7oBkMLTfGmpIxoKQFwXlzWLtffcQIpX/1no+iNPxwQ=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
@@ -75,25 +89,18 @@ github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ=
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
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/sunglocto/oasis-sdk v0.0.0-20251128101950-083ea4658d9c h1:peWSGIl0xBvx3sJR3+kHV1xOe1X8dbQ9xtvEXyXogCo=
github.com/sunglocto/oasis-sdk v0.0.0-20251128101950-083ea4658d9c/go.mod h1:Y5iPruMLvqNwGVqB+n/+wylQjCTPKQx37I/PyLWhuzk=
github.com/sunglocto/oasis-sdk v0.0.0-20260103140045-0405de0dd080 h1:29bQpS8K/agBsO2fkXXyId3aDBweVIA+USUNmQpwdac=
github.com/sunglocto/oasis-sdk v0.0.0-20260103140045-0405de0dd080/go.mod h1:Y5iPruMLvqNwGVqB+n/+wylQjCTPKQx37I/PyLWhuzk=
github.com/sunglocto/oasis-sdk v0.0.0-20260103140638-616fcb543bcf h1:yC8TNIiaJtxzP2hIABRe7EdhcSAODUVkjzsici5Fohw=
github.com/sunglocto/oasis-sdk v0.0.0-20260103140638-616fcb543bcf/go.mod h1:Y5iPruMLvqNwGVqB+n/+wylQjCTPKQx37I/PyLWhuzk=
github.com/sunglocto/oasis-sdk v0.0.0-20260103140748-3a5af37a9707 h1:r7CKzHIBlp2Cq28WrCe2VaKdZCD4dCd1BmxXLno7Mcg=
github.com/sunglocto/oasis-sdk v0.0.0-20260103140748-3a5af37a9707/go.mod h1:Y5iPruMLvqNwGVqB+n/+wylQjCTPKQx37I/PyLWhuzk=
github.com/sunglocto/oasis-sdk v0.0.0-20260103140915-72af6e4c3604 h1:yD8c7E3FECQ45Amrn4FnxBw30XbBgfQ+exgbA5IisEU=
github.com/sunglocto/oasis-sdk v0.0.0-20260103140915-72af6e4c3604/go.mod h1:Y5iPruMLvqNwGVqB+n/+wylQjCTPKQx37I/PyLWhuzk=
github.com/sunglocto/oasis-sdk v0.0.0-20260103142016-f599b73f44e3 h1:S1miV9gK4GKqr+RdmqW71JnpYhoFZehe9NkABbM2XW4=
github.com/sunglocto/oasis-sdk v0.0.0-20260103142016-f599b73f44e3/go.mod h1:Y5iPruMLvqNwGVqB+n/+wylQjCTPKQx37I/PyLWhuzk=
github.com/sunglocto/oasis-sdk v0.0.0-20260103142127-cc8ce586b6dc h1:7KKRazjvG5I1l+hyvTvM8XLIWewGQ2PAaKr4sN1Oi7E=
github.com/sunglocto/oasis-sdk v0.0.0-20260103142127-cc8ce586b6dc/go.mod h1:Y5iPruMLvqNwGVqB+n/+wylQjCTPKQx37I/PyLWhuzk=
github.com/sunglocto/oasis-sdk v0.0.0-20260103142308-7f1848e2aac0 h1:7zNLaQVg8jYYrNZ6KqBv23k/RYu58p3wL9YS72B+eNM= github.com/sunglocto/oasis-sdk v0.0.0-20260103142308-7f1848e2aac0 h1:7zNLaQVg8jYYrNZ6KqBv23k/RYu58p3wL9YS72B+eNM=
github.com/sunglocto/oasis-sdk v0.0.0-20260103142308-7f1848e2aac0/go.mod h1:Y5iPruMLvqNwGVqB+n/+wylQjCTPKQx37I/PyLWhuzk= github.com/sunglocto/oasis-sdk v0.0.0-20260103142308-7f1848e2aac0/go.mod h1:Y5iPruMLvqNwGVqB+n/+wylQjCTPKQx37I/PyLWhuzk=
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/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
@@ -107,6 +114,7 @@ golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
+193 -65
View File
@@ -3,9 +3,13 @@ package main
import ( import (
//core - required //core - required
"context" "context"
_ "embed"
"encoding/xml" "encoding/xml"
"errors" "errors"
"fmt" "fmt"
"image/color"
_ "image/jpeg"
_ "image/png"
"io" "io"
"log" "log"
"math/rand/v2" "math/rand/v2"
@@ -13,9 +17,6 @@ import (
"os" "os"
"strings" "strings"
"time" "time"
_ "embed"
_ "image/png"
_ "image/jpeg"
// gui - required // gui - required
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
@@ -27,25 +28,27 @@ import (
"fyne.io/fyne/v2/storage" "fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
extraWidgets "fyne.io/x/fyne/widget" "fyne.io/fyne/v2/layout"
"github.com/gen2brain/beeep"
"github.com/makeworld-the-better-one/go-isemoji" "github.com/makeworld-the-better-one/go-isemoji"
"github.com/rrivera/identicon" "github.com/rrivera/identicon"
"github.com/shreve/musicwand/pkg/mpris" "github.com/shreve/musicwand/pkg/mpris"
// xmpp - required // xmpp - required
oasisSdk "github.com/sunglocto/oasis-sdk"
"mellium.im/xmpp/bookmarks" "mellium.im/xmpp/bookmarks"
xmppColor "mellium.im/xmpp/color"
"mellium.im/xmpp/jid" "mellium.im/xmpp/jid"
"mellium.im/xmpp/muc" "mellium.im/xmpp/muc"
"mellium.im/xmpp/stanza"
"mellium.im/xmpp/pubsub" "mellium.im/xmpp/pubsub"
oasisSdk "github.com/sunglocto/oasis-sdk" "mellium.im/xmpp/stanza"
// TODO: integrated theme switcher // TODO: integrated theme switcher
) )
//go:embed pi.png //go:embed pi.png
var iconBytes []byte var iconBytes []byte
var version string = "3.1i" var version string = "3.14i"
var statBar widget.Label var statBar widget.Label
var chatInfo fyne.Container var chatInfo fyne.Container
var chatSidebar fyne.Container var chatSidebar fyne.Container
@@ -53,6 +56,7 @@ var replyNameIcon string = ">"
var replyBodyIcon string = ">" var replyBodyIcon string = ">"
var newlineIcon string = " |-> " var newlineIcon string = " |-> "
var agreesToSendingHotFuckIntoChannel bool = false var agreesToSendingHotFuckIntoChannel bool = false
var sendEmpty bool = false
var OccupantIdsToBlock = make(map[string]string) var OccupantIdsToBlock = make(map[string]string)
// by sunglocto // by sunglocto
@@ -64,6 +68,7 @@ type Message struct {
ID string ID string
ReplyID string ReplyID string
ImageURL string ImageURL string
Corrected bool
Raw oasisSdk.XMPPChatMessage Raw oasisSdk.XMPPChatMessage
Important bool Important bool
Readers []jid.JID Readers []jid.JID
@@ -167,14 +172,14 @@ func CreateUITab(chatJidStr string) ChatTabUI {
im := ii.Image(25) im := ii.Image(25)
ico := canvas.NewImageFromImage(im) ico := canvas.NewImageFromImage(im)
ico.FillMode = canvas.ImageFillOriginal ico.FillMode = canvas.ImageFillOriginal
author := widget.NewLabel("author") author := canvas.NewText("author", color.RGBA{255, 255, 255, 255})
author.TextStyle.Bold = true author.TextStyle.Bold = true
author.Selectable = true // author.Selectable = true
content := widget.NewLabel("content") content := widget.NewLabel("content")
content.Wrapping = fyne.TextWrapWord content.Wrapping = fyne.TextWrapWord
content.Selectable = true content.Selectable = true
content.Importance = widget.MediumImportance content.Importance = widget.MediumImportance
//content.SizeName = fyne.ThemeSizeName(theme.SizeNameText) content.SizeName = fyne.ThemeSizeName(theme.SizeNameText)
icon := theme.FileVideoIcon() icon := theme.FileVideoIcon()
replytext := widget.NewLabel(">fallback reply text") replytext := widget.NewLabel(">fallback reply text")
replytext.Hide() replytext.Hide()
@@ -189,7 +194,10 @@ func CreateUITab(chatJidStr string) ChatTabUI {
reactions := container.NewHBox() reactions := container.NewHBox()
return container.NewVBox(replytext, container.NewHBox(ico, author), content, btn, reactions) pencil := widget.NewButtonWithIcon("", theme.DocumentCreateIcon(), func(){})
pencil.Hidden = true
return container.NewVBox(replytext, container.NewHBox(ico, author, layout.NewSpacer(), pencil), content, btn, reactions)
}, },
func(i widget.ListItemID, co fyne.CanvasObject) { func(i widget.ListItemID, co fyne.CanvasObject) {
@@ -205,9 +213,14 @@ func CreateUITab(chatJidStr string) ChatTabUI {
authorBox.Objects[0].(*canvas.Image).FillMode = canvas.ImageFillOriginal authorBox.Objects[0].(*canvas.Image).FillMode = canvas.ImageFillOriginal
authorBox.Objects[0].Refresh() authorBox.Objects[0].Refresh()
pencil := authorBox.Objects[3].(*widget.Button)
// Icon generate end // Icon generate end
author := authorBox.Objects[1].(*widget.Label) author := authorBox.Objects[1].(*canvas.Text)
col := xmppColor.String(chatTabs[chatJidStr].Messages[i].Author, 0, xmppColor.None)
author.Color = col
content := vbox.Objects[2].(*widget.Label) content := vbox.Objects[2].(*widget.Label)
unknown_tags := chatTabs[chatJidStr].Messages[i].Raw.Unknown unknown_tags := chatTabs[chatJidStr].Messages[i].Raw.Unknown
for _, v := range unknown_tags { for _, v := range unknown_tags {
@@ -216,8 +229,9 @@ func CreateUITab(chatJidStr string) ChatTabUI {
if attr.Name.Local == "id" { if attr.Name.Local == "id" {
reason, ok := OccupantIdsToBlock[attr.Value] reason, ok := OccupantIdsToBlock[attr.Value]
if ok { if ok {
author.SetText("Ignored user") author.Text = ("Ignored user")
content.SetText("This user is ignored due to: " + reason) content.SetText("This user is ignored due to: " + reason)
content.Importance = widget.LowImportance
return // message is from blocked user return // message is from blocked user
} }
} }
@@ -236,7 +250,20 @@ func CreateUITab(chatJidStr string) ChatTabUI {
if chatTabs[chatJidStr].Messages[i].Important { if chatTabs[chatJidStr].Messages[i].Important {
content.Importance = widget.DangerImportance content.Importance = widget.DangerImportance
} else {
content.Importance = widget.MediumImportance
} }
if chatTabs[chatJidStr].Messages[i].Corrected {
pencil.Hidden = false
pencil.OnTapped = func() {
dialog.ShowInformation("Original", *chatTabs[chatJidStr].Messages[i].Raw.CleanedBody, w)
}
} else {
pencil.Hidden = true
}
btn.Hidden = true // Hide by default btn.Hidden = true // Hide by default
msgContent := chatTabs[chatJidStr].Messages[i].Content msgContent := chatTabs[chatJidStr].Messages[i].Content
if chatTabs[chatJidStr].Messages[i].Raw.OutOfBandMedia != nil { if chatTabs[chatJidStr].Messages[i].Raw.OutOfBandMedia != nil {
@@ -296,27 +323,31 @@ func CreateUITab(chatJidStr string) ChatTabUI {
for i := len(chatTabs[chatJidStr].Messages) - 1; i >= 0; i-- { for i := len(chatTabs[chatJidStr].Messages) - 1; i >= 0; i-- {
if reply.ID == chatTabs[chatJidStr].Messages[i].Raw.StanzaID.ID { if reply.ID == chatTabs[chatJidStr].Messages[i].Raw.StanzaID.ID {
replytext.Show() replytext.Show()
replytext.SetText(fmt.Sprintf("%s %s", replyBodyIcon, strings.ReplaceAll(chatTabs[chatJidStr].Messages[i].Content, "\n", newlineIcon))) replytext.Text = fmt.Sprintf("%s %s", replyBodyIcon, strings.ReplaceAll(chatTabs[chatJidStr].Messages[i].Content, "\n", newlineIcon))
guy = chatTabs[chatJidStr].Messages[i].Author guy = chatTabs[chatJidStr].Messages[i].Author
break break
} }
} }
author.SetText(fmt.Sprintf("%s %s %s", chatTabs[chatJidStr].Messages[i].Author, replyNameIcon, guy)) author.Text = (fmt.Sprintf("%s %s %s", chatTabs[chatJidStr].Messages[i].Author, replyNameIcon, guy))
} else { } else {
author.SetText(chatTabs[chatJidStr].Messages[i].Author) author.Text = (chatTabs[chatJidStr].Messages[i].Author)
replytext.Hide() replytext.Hide()
} }
sl := strings.Split(msgContent, " ") sl := strings.Split(msgContent, " ")
content.SizeName = fyne.ThemeSizeName(theme.SizeNameText)
if len(sl) == 1 && isemoji.IsEmoji(sl[0]) { if len(sl) == 1 && isemoji.IsEmoji(sl[0]) {
content.SizeName = fyne.ThemeSizeName(theme.SizeNameHeadingText) content.SizeName = fyne.ThemeSizeName(theme.SizeNameHeadingText)
content.Refresh() content.Refresh()
} else {
content.SizeName = fyne.ThemeSizeName(theme.SizeNameText)
content.Refresh()
} }
if sl[0] == "/me" { if sl[0] == "/me" {
author.SetText(author.Text + " " + strings.Join(sl[1:], " ")) author.Text = (author.Text + " " + strings.Join(sl[1:], " "))
content.SetText(" ") content.SetText(" ")
} }
@@ -434,7 +465,9 @@ func dropToSignInPage(reason string) {
dialog.ShowError(err, w) dialog.ShowError(err, w)
return return
} }
a.SendNotification(fyne.NewNotification("Done", "Relaunch the application")) // a.SendNotification(fyne.NewNotification("Done", "Relaunch the application"))
beeep.Notify("Done", "Relaunch the application", iconBytes)
a.Quit() a.Quit()
//w.Close() //w.Close()
} }
@@ -449,6 +482,7 @@ func dropToSignInPage(reason string) {
} }
func main() { func main() {
beeep.AppName = "pi"
muc.Since(time.Now()) muc.Since(time.Now())
config = piConfig{} config = piConfig{}
res := fyne.NewStaticResource("image", iconBytes) res := fyne.NewStaticResource("image", iconBytes)
@@ -493,7 +527,8 @@ func main() {
if ok { if ok {
str := *msg.CleanedBody str := *msg.CleanedBody
if notifications { if notifications {
a.SendNotification(fyne.NewNotification(fmt.Sprintf("%s says", userJidStr), str)) // a.SendNotification(fyne.NewNotification(fmt.Sprintf("%s says", userJidStr), str))
beeep.Notify("Direct message", fmt.Sprintf("%s says:\n%s", userJidStr, str), iconBytes)
} }
for _, v := range msg.Unknown { for _, v := range msg.Unknown {
@@ -531,7 +566,9 @@ func main() {
if correction { if correction {
for i := len(tab.Messages) - 1; i > 0; i-- { for i := len(tab.Messages) - 1; i > 0; i-- {
if tab.Messages[i].Raw.From.String() == msg.From.String() { if tab.Messages[i].Raw.From.String() == msg.From.String() {
tab.Messages[i].Content = *msg.CleanedBody + " (corrected)" // tab.Messages[i].Content = *msg.CleanedBody + " (corrected)"
tab.Messages[i].Content = *msg.CleanedBody
tab.Messages[i].Corrected = true
fyne.Do(func() { fyne.Do(func() {
UITabs[userJidStr].Scroller.Refresh() UITabs[userJidStr].Scroller.Refresh()
}) })
@@ -599,7 +636,8 @@ func main() {
} }
if !donotnotify && !ignore && notifications { if !donotnotify && !ignore && notifications {
if !correction && msg.From.String() != client.JID.String() && strings.Contains(str, login.DisplayName) || (msg.Reply != nil && strings.Contains(msg.Reply.To, login.DisplayName)) { if !correction && msg.From.String() != client.JID.String() && strings.Contains(str, login.DisplayName) || (msg.Reply != nil && strings.Contains(msg.Reply.To, login.DisplayName)) {
a.SendNotification(fyne.NewNotification(fmt.Sprintf("Mentioned in %s", mucJidStr), str)) // a.SendNotification(fyne.NewNotification(fmt.Sprintf("Mentioned in %s", mucJidStr), str))
beeep.Notify(fmt.Sprintf("Mentioned in %s by %s", jid.MustParse(mucJidStr).Localpart(), msg.From.Resourcepart()), str, iconBytes)
} }
} }
if strings.Contains(str, "https://") { if strings.Contains(str, "https://") {
@@ -640,7 +678,9 @@ func main() {
if correction { if correction {
for i := len(tab.Messages) - 1; i > 0; i-- { for i := len(tab.Messages) - 1; i > 0; i-- {
if tab.Messages[i].Raw.From.String() == msg.From.String() { if tab.Messages[i].Raw.From.String() == msg.From.String() {
tab.Messages[i].Content = *msg.CleanedBody + " (corrected)" // tab.Messages[i].Content = *msg.CleanedBody + " (corrected)"
tab.Messages[i].Content = *msg.CleanedBody
tab.Messages[i].Corrected = true
fyne.Do(func() { fyne.Do(func() {
UITabs[mucJidStr].Scroller.Refresh() UITabs[mucJidStr].Scroller.Refresh()
}) })
@@ -664,6 +704,10 @@ func main() {
} }
important = false important = false
fyne.Do(func() { fyne.Do(func() {
_, ok := UITabs[mucJidStr]
if !ok {
return
}
UITabs[mucJidStr].Scroller.Refresh() UITabs[mucJidStr].Scroller.Refresh()
if scrollDownOnNewMessage { if scrollDownOnNewMessage {
tab, ok := UITabs[mucJidStr] tab, ok := UITabs[mucJidStr]
@@ -797,6 +841,7 @@ func main() {
}, w) }, w)
}) })
w.Resize(fyne.NewSize(500, 500)) w.Resize(fyne.NewSize(500, 500))
w.SetIcon(res)
entry := NewCustomMultiLineEntry() entry := NewCustomMultiLineEntry()
entry.SetPlaceHolder("Say something, you know you want to.\nCtrl+Enter for newline") entry.SetPlaceHolder("Say something, you know you want to.\nCtrl+Enter for newline")
@@ -805,7 +850,13 @@ func main() {
SendCallback := func() { SendCallback := func() {
text := entry.Text text := entry.Text
if AppTabs.Selected() == nil || AppTabs.Selected().Content == nil || text == "" { if text == "" {
dialog.ShowConfirm("Empty message", "Send an empty message?", func(b bool) {
sendEmpty = b
}, w)
}
if AppTabs.Selected() == nil || AppTabs.Selected().Content == nil || (text == "" && !sendEmpty) {
return return
} }
@@ -1058,6 +1109,34 @@ func main() {
}, w) }, w)
}) })
getMAM := fyne.NewMenuItem("send stanza", func() {
sendiq := false
b := container.NewVBox()
note := widget.NewRichTextFromMarkdown(fmt.Sprintf("# How to send a stanza\nThe stanza must be formed properly or the client will disconnect! Some actions such as joining rooms should be done via the client.\n Here is an example of a typical stanza:\n\n```\n<message from=abc@example.com to=xyz@example.com type=chat>\n\t<body>We have had a most delightful evening, a most excellent ball.</body>\n</message>\n```\n\nThe `from` attribute should be your JID `(%s)` and the `to` attribute should be the intended recipient. The `type` attribute can be `chat`, `groupchat`, `headline` and more.\n\nFor more information, read [RFC 6120](https://www.rfc-editor.org/rfc/rfc6120.html).", client.JID.String()))
note.Hidden = true
// note.Wrapping = fyne.TextWrapWord
b.Add(note)
isiq := widget.NewCheck("IQ stanza (get a reponse back)", func(b bool) {sendiq=b})
b.Add(isiq)
hlpbtn := widget.NewButton("Help!", func() {note.Hidden = !note.Hidden})
b.Add(hlpbtn)
entry := widget.NewMultiLineEntry()
entry.SetPlaceHolder(fmt.Sprintf("<message type='chat' from='%s' id='ilovepi' to='friend@home.org'><body>Hello from Pi!</body></message>", client.JID.String()))
b.Add(entry)
btn := widget.NewButton("Send", func() {
fmt.Println(sendiq)
msg := entry.Text
err := client.Session.Send(context.TODO(), xml.NewDecoder(strings.NewReader(msg)))
if err != nil {
dialog.ShowError(err, w)
return
}
})
b.Add(btn)
dialog.ShowCustom("Send a custom XML stanza", "Close", b, w)
})
leaveRoom := fyne.NewMenuItem("disconnect from current room", func() { leaveRoom := fyne.NewMenuItem("disconnect from current room", func() {
selectedScroller, ok := AppTabs.Selected().Content.(*widget.List) selectedScroller, ok := AppTabs.Selected().Content.(*widget.List)
if !ok { if !ok {
@@ -1170,19 +1249,19 @@ func main() {
setNick = widget.NewButton("Set nick", func() { setNick = widget.NewButton("Set nick", func() {
go func() { go func() {
fyne.Do(func() {setNick.Disable()}) fyne.Do(func() { setNick.Disable() })
newNick := nickEntry.Text newNick := nickEntry.Text
bookmark.Nick = newNick bookmark.Nick = newNick
err := client.PublishBookmark(bookmark, context.TODO()) err := client.PublishBookmark(bookmark, context.TODO())
if err != nil { if err != nil {
fyne.Do(func() { fyne.Do(func() {
setNick.Enable() setNick.Enable()
dialog.ShowError(err, w) dialog.ShowError(err, w)
}) })
return return
} }
client.RefreshBookmarks(false) client.RefreshBookmarks(false)
fyne.Do(func() {setNick.Enable()}) fyne.Do(func() { setNick.Enable() })
}() }()
}) })
@@ -1206,14 +1285,7 @@ func main() {
joinARoom := fyne.NewMenuItem("connect to a room", func() { joinARoom := fyne.NewMenuItem("connect to a room", func() {
dialog.ShowEntryDialog("connect to a room", "JID:", func(s string) { dialog.ShowEntryDialog("connect to a room", "JID:", func(s string) {
i := resourcePiloadingGif d := dialog.NewCustom("Please wait", "Close", widget.NewProgressBarInfinite(), w)
gif, err := extraWidgets.NewAnimatedGifFromResource(i)
if err != nil {
panic(err)
}
gif.Start()
gif.Show()
d := dialog.NewCustom("Please wait", "Close", gif, w)
d.Show() d.Show()
go func() { go func() {
myjid, err := jid.Parse(s) myjid, err := jid.Parse(s)
@@ -1242,14 +1314,7 @@ func main() {
beginADM := fyne.NewMenuItem("start a DM", func() { beginADM := fyne.NewMenuItem("start a DM", func() {
dialog.ShowEntryDialog("Start a DM", "JID:", func(s string) { dialog.ShowEntryDialog("Start a DM", "JID:", func(s string) {
i := resourcePiloadingGif d := dialog.NewCustom("Please wait", "Close", widget.NewLabel("Opening a DM with "+s), w)
gif, err := extraWidgets.NewAnimatedGifFromResource(i)
if err != nil {
panic(err)
}
gif.Start()
gif.Show()
d := dialog.NewCustom("Please wait", "Close", gif, w)
d.Show() d.Show()
go func() { go func() {
myjid, err := jid.Parse(s) myjid, err := jid.Parse(s)
@@ -1267,7 +1332,7 @@ func main() {
menu_help := fyne.NewMenu("π", mit, reconnect, licensesbtn) menu_help := fyne.NewMenu("π", mit, reconnect, licensesbtn)
menu_changeroom := fyne.NewMenu("Α", mic, beginADM, joinARoom, leaveRoom, manageBookmarks) menu_changeroom := fyne.NewMenu("Α", mic, beginADM, joinARoom, leaveRoom, manageBookmarks, getMAM)
menu_configureview := fyne.NewMenu("Β", mia, jtt, jtb) menu_configureview := fyne.NewMenu("Β", mia, jtt, jtb)
hafjag := fyne.NewMenuItem("Hafjag", func() { hafjag := fyne.NewMenuItem("Hafjag", func() {
entry.Text = "Hafjag" entry.Text = "Hafjag"
@@ -1314,6 +1379,13 @@ func main() {
entry.Text = old entry.Text = old
}) })
wspeed := fyne.NewMenuItem("W Speed ❤️‍🩹❤️‍🩹", func() {
old := entry.Text
entry.Text = "W Speed ❤️‍🩹❤️‍🩹"
SendCallback()
entry.Text = old
})
exposed_suffix := fyne.NewMenuItem(".exposed", func() { exposed_suffix := fyne.NewMenuItem(".exposed", func() {
selectedScroller, ok := AppTabs.Selected().Content.(*widget.List) selectedScroller, ok := AppTabs.Selected().Content.(*widget.List)
if !ok { if !ok {
@@ -1390,7 +1462,7 @@ func main() {
} }
}) })
menu_jokes := fyne.NewMenu("Δ", mycurrenttime, mycurrentplayingsong, hafjag, hotfuck, agree, kai, mipipiemi, exposed_suffix) menu_jokes := fyne.NewMenu("Δ", mycurrenttime, mycurrentplayingsong, hafjag, hotfuck, agree, kai, mipipiemi, exposed_suffix, wspeed)
bit := fyne.NewMenuItem("mark selected message as read", func() { bit := fyne.NewMenuItem("mark selected message as read", func() {
selectedScroller, ok := AppTabs.Selected().Content.(*widget.List) selectedScroller, ok := AppTabs.Selected().Content.(*widget.List)
if !ok { if !ok {
@@ -1408,6 +1480,36 @@ func main() {
client.MarkAsRead(&m) client.MarkAsRead(&m)
}) })
rec := fyne.NewMenuItem("retract selected message", func() {
selectedScroller, ok := AppTabs.Selected().Content.(*widget.List)
if !ok {
return
}
var activeMucJid string
for jid, tabData := range UITabs {
if tabData.Scroller == selectedScroller {
activeMucJid = jid
break
}
}
if !chatTabs[activeMucJid].isMuc {
return // TODO: For 1:1 DMs we use OccupantID for the ID and send message type 'chat'
}
id := chatTabs[activeMucJid].Messages[selectedId].Raw.StanzaID
if id == nil {
return
}
msg := fmt.Sprintf("<message type='groupchat' to='%s' id='retract-message-1'><retract id='%s' xmlns='urn:xmpp:message-retract:1'/><fallback xmlns='urn:xmpp:fallback:0' for='urn:xmpp:message-retract:1' /><body>This user retracted a previous message, but it's unsupported by your client.</body><store xmlns='urn:xmpp:hints'/></message>", activeMucJid, id.ID)
fmt.Println(msg)
err := client.Session.Send(context.TODO(), xml.NewDecoder(strings.NewReader(msg)))
if err != nil {
dialog.ShowError(err, w)
}
})
bia := fyne.NewMenuItem("toggle replying to message", func() { bia := fyne.NewMenuItem("toggle replying to message", func() {
replying = !replying replying = !replying
}) })
@@ -1517,7 +1619,7 @@ func main() {
dialog.ShowCustom("Message", "Close", pre, w) dialog.ShowCustom("Message", "Close", pre, w)
}) })
menu_messageoptions := fyne.NewMenu("Γ", bit, bia, bic, red, blck) menu_messageoptions := fyne.NewMenu("Γ", bit, bia, bic, rec, red, blck)
ma := fyne.NewMainMenu(menu_help, menu_changeroom, menu_configureview, menu_messageoptions, menu_jokes) ma := fyne.NewMainMenu(menu_help, menu_changeroom, menu_configureview, menu_messageoptions, menu_jokes)
w.SetMainMenu(ma) w.SetMainMenu(ma)
@@ -1558,9 +1660,9 @@ func main() {
dialog.ShowError(err, w) dialog.ShowError(err, w)
} }
fyne.Do(func() { fyne.Do(func() {
AppTabs.Selected().Text = fmt.Sprintf("%s (disconnected)", AppTabs.Selected().Text) AppTabs.Selected().Text = fmt.Sprintf("%s (disconnected)", AppTabs.Selected().Text)
AppTabs.Remove(ti) AppTabs.Remove(ti)
delete(UITabs, activeChatJid) delete(UITabs, activeChatJid)
}) })
}() }()
} }
@@ -1573,6 +1675,16 @@ func main() {
} }
} }
AppTabs.OnUnselected = func(ti *container.TabItem) {
selectedScroller, ok := AppTabs.Selected().Content.(*widget.List)
if !ok {
return
}
selectedScroller.Hidden = true
}
var MainSplit *container.Split
AppTabs.OnSelected = func(ti *container.TabItem) { AppTabs.OnSelected = func(ti *container.TabItem) {
chatSidebar.Resize(chatSidebar.Size()) chatSidebar.Resize(chatSidebar.Size())
if AppTabs.Selected() == AppTabs.Items[0] { if AppTabs.Selected() == AppTabs.Items[0] {
@@ -1584,6 +1696,8 @@ func main() {
return return
} }
selectedScroller.Hidden = false
var activeChatJid string var activeChatJid string
for jid, tabData := range UITabs { for jid, tabData := range UITabs {
if tabData.Scroller == selectedScroller { if tabData.Scroller == selectedScroller {
@@ -1601,8 +1715,8 @@ func main() {
nameLabel.Truncation = fyne.TextTruncateEllipsis nameLabel.Truncation = fyne.TextTruncateEllipsis
memberLabel := widget.NewLabel(fmt.Sprintf("%d members ", len(tab.Members))) memberLabel := widget.NewLabel(fmt.Sprintf("%d members ", len(tab.Members)))
memberLabel.Truncation = fyne.TextTruncateEllipsis memberLabel.Truncation = fyne.TextTruncateEllipsis
box := container.NewVBox(nameLabel, ) box := container.NewVBox(nameLabel)
chatSidebar.Objects = []fyne.CanvasObject{} // chatSidebar.Objects = []fyne.CanvasObject{}
for name, p := range tab.Members { for name, p := range tab.Members {
log.Println(string(p.Type)) log.Println(string(p.Type))
@@ -1644,24 +1758,28 @@ func main() {
} }
s.Truncation = fyne.TextTruncateEllipsis s.Truncation = fyne.TextTruncateEllipsis
box.Add(s) box.Add(s)
box.Refresh()
} }
} }
} }
chatSidebar = *container.NewGridWithColumns(1, container.NewVScroll(box)) chatSidebar = *container.NewGridWithColumns(1, container.NewVScroll(box))
} else { } else {
chatSidebar = *container.NewVBox(widget.NewRichTextFromMarkdown("# " + activeChatJid)) if activeChatJid == config.Login.User {
chatSidebar = *container.NewVBox(widget.NewRichTextFromMarkdown("# "+activeChatJid), widget.NewLabel("Hey, that's you!"))
} else {
chatSidebar = *container.NewVBox(widget.NewRichTextFromMarkdown("# " + activeChatJid))
}
} }
chatSidebar.Hidden = false chatSidebar.Hidden = false
chatSidebar.Refresh() chatSidebar.Show()
chatSidebar.Resize(chatSidebar.Size()) MainSplit.Resize(MainSplit.Size())
} }
chatSidebar.Hidden = false chatSidebar.Hidden = false
statBar.SetText("") statBar.SetText("")
chatInfo = *container.NewHBox(widget.NewLabel("")) chatInfo = *container.NewHBox(widget.NewLabel(""))
MainSplit := container.NewHSplit(AppTabs, &chatSidebar) MainSplit = container.NewHSplit(AppTabs, &chatSidebar)
DownSplit := container.NewHSplit(entry, container.NewGridWithRows(1, sendbtn, replybtn)) DownSplit := container.NewHSplit(entry, container.NewGridWithRows(1, sendbtn, replybtn))
BigSplit := container.NewVSplit(MainSplit, DownSplit) BigSplit := container.NewVSplit(MainSplit, DownSplit)
@@ -1673,5 +1791,15 @@ func main() {
MasterSplit.SetOffset(1) MasterSplit.SetOffset(1)
w.SetContent(MasterSplit) w.SetContent(MasterSplit)
if time.Now().Month() == time.April && time.Now().Day() == 1 {
dialog.ShowConfirm("We care about your privacy", "We and our 5832 partner(s) would like to use your data for the following purposes:\n- Selling your organs\n- Stealing your identity\n- Putting you in jail\nYou're in control of your in data.\nDo you want us to do this? We'll do it anyway if you say no.", func(b bool) {
if b {
u, err := url.Parse("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
if err == nil {
a.OpenURL(u)
}
}
}, w)
}
w.ShowAndRun() w.ShowAndRun()
} }
-12
View File
File diff suppressed because one or more lines are too long