diff --git a/go.mod b/go.mod
index 59e7bde..d77685d 100644
--- a/go.mod
+++ b/go.mod
@@ -4,6 +4,7 @@ go 1.25.1
require (
fyne.io/fyne/v2 v2.7.1
+ 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/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d
@@ -35,7 +36,6 @@ require (
github.com/jackmordaunt/icns/v3 v3.0.1 // indirect
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade // indirect
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect
- github.com/kr/text v0.2.0 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/nicksnyder/go-i18n/v2 v2.5.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
diff --git a/go.sum b/go.sum
index 247ee30..02dfb31 100644
--- a/go.sum
+++ b/go.sum
@@ -2,13 +2,14 @@ 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/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/x/fyne v0.0.0-20251214153509-fa68a7d234d5 h1:kDuBckHtdKTNV+jq0AornXroGSd/GMq06dBNXOWfmyY=
+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 v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
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=
diff --git a/main.go b/main.go
index 7666443..91e9c84 100644
--- a/main.go
+++ b/main.go
@@ -7,13 +7,13 @@ import (
"encoding/xml"
"errors"
"fmt"
+ "image/color"
_ "image/jpeg"
_ "image/png"
"io"
"log"
"math/rand/v2"
"net/url"
- "image/color"
"os"
"strings"
"time"
@@ -28,19 +28,19 @@ import (
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
+ "github.com/gen2brain/beeep"
"github.com/makeworld-the-better-one/go-isemoji"
"github.com/rrivera/identicon"
"github.com/shreve/musicwand/pkg/mpris"
- "github.com/gen2brain/beeep"
// xmpp - required
oasisSdk "github.com/sunglocto/oasis-sdk"
"mellium.im/xmpp/bookmarks"
+ xmppColor "mellium.im/xmpp/color"
"mellium.im/xmpp/jid"
"mellium.im/xmpp/muc"
"mellium.im/xmpp/pubsub"
"mellium.im/xmpp/stanza"
- xmppColor "mellium.im/xmpp/color"
// TODO: integrated theme switcher
)
@@ -55,6 +55,7 @@ var replyNameIcon string = ">"
var replyBodyIcon string = ">"
var newlineIcon string = " |-> "
var agreesToSendingHotFuckIntoChannel bool = false
+var sendEmpty bool = false
var OccupantIdsToBlock = make(map[string]string)
// by sunglocto
@@ -211,7 +212,7 @@ func CreateUITab(chatJidStr string) ChatTabUI {
author := authorBox.Objects[1].(*canvas.Text)
col := xmppColor.String(chatTabs[chatJidStr].Messages[i].Author, 0, xmppColor.None)
- author.Color = col
+ author.Color = col
content := vbox.Objects[2].(*widget.Label)
unknown_tags := chatTabs[chatJidStr].Messages[i].Raw.Unknown
@@ -680,6 +681,10 @@ func main() {
}
important = false
fyne.Do(func() {
+ _, ok := UITabs[mucJidStr]
+ if !ok {
+ return
+ }
UITabs[mucJidStr].Scroller.Refresh()
if scrollDownOnNewMessage {
tab, ok := UITabs[mucJidStr]
@@ -822,7 +827,13 @@ func main() {
SendCallback := func() {
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
}
@@ -1075,6 +1086,34 @@ func main() {
}, 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\n\tWe have had a most delightful evening, a most excellent ball.\n\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("Hello from Pi!", 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() {
selectedScroller, ok := AppTabs.Selected().Content.(*widget.List)
if !ok {
@@ -1223,7 +1262,7 @@ func main() {
joinARoom := fyne.NewMenuItem("connect to a room", func() {
dialog.ShowEntryDialog("connect to a room", "JID:", func(s string) {
- d := dialog.NewCustom("Please wait", "Close", widget.NewLabel("Connecting to "+s), w)
+ d := dialog.NewCustom("Please wait", "Close", widget.NewProgressBarInfinite(), w)
d.Show()
go func() {
myjid, err := jid.Parse(s)
@@ -1252,7 +1291,7 @@ func main() {
beginADM := fyne.NewMenuItem("start a DM", func() {
dialog.ShowEntryDialog("Start a DM", "JID:", func(s string) {
- d := dialog.NewCustom("Please wait", "Close", widget.NewLabel("Opening a DM with " + s), w)
+ d := dialog.NewCustom("Please wait", "Close", widget.NewLabel("Opening a DM with "+s), w)
d.Show()
go func() {
myjid, err := jid.Parse(s)
@@ -1270,7 +1309,7 @@ func main() {
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)
hafjag := fyne.NewMenuItem("Hafjag", func() {
entry.Text = "Hafjag"
@@ -1303,8 +1342,6 @@ func main() {
entry.Text = old
})
-
-
kai := fyne.NewMenuItem("kai cenat beg", func() {
old := entry.Text
entry.Text = "chat will you subscribe to save the kai cenat mafiathon 3"
@@ -1706,7 +1743,7 @@ func main() {
chatSidebar = *container.NewGridWithColumns(1, container.NewVScroll(box))
} else {
if activeChatJid == config.Login.User {
- chatSidebar = *container.NewVBox(widget.NewRichTextFromMarkdown("# " + activeChatJid), widget.NewLabel("Hey, that's you!"))
+ chatSidebar = *container.NewVBox(widget.NewRichTextFromMarkdown("# "+activeChatJid), widget.NewLabel("Hey, that's you!"))
} else {
chatSidebar = *container.NewVBox(widget.NewRichTextFromMarkdown("# " + activeChatJid))
}