format + allow closing
This commit is contained in:
@@ -140,7 +140,6 @@ var moderateBytes []byte
|
|||||||
//go:embed assets/jabber.png
|
//go:embed assets/jabber.png
|
||||||
var jabberBytes []byte
|
var jabberBytes []byte
|
||||||
|
|
||||||
|
|
||||||
//go:embed assets/fail.png
|
//go:embed assets/fail.png
|
||||||
var failBytes []byte
|
var failBytes []byte
|
||||||
|
|
||||||
|
|||||||
+32
-3
@@ -14,9 +14,9 @@ import (
|
|||||||
"github.com/rrivera/identicon"
|
"github.com/rrivera/identicon"
|
||||||
"gosrc.io/xmpp/stanza"
|
"gosrc.io/xmpp/stanza"
|
||||||
"image"
|
"image"
|
||||||
|
"image/color"
|
||||||
"image/png"
|
"image/png"
|
||||||
xmpp_color "mellium.im/xmpp/color"
|
xmpp_color "mellium.im/xmpp/color"
|
||||||
"image/color"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -54,6 +54,34 @@ func createTab(jid string, isMuc bool, name string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func removeTab(jid string, w *gtk.Window) {
|
||||||
|
t, ok := tabs.Load(jid)
|
||||||
|
if ok {
|
||||||
|
tab := t.(*chatTab)
|
||||||
|
tab.msgs.RemoveAll()
|
||||||
|
if tab.isMuc {
|
||||||
|
client.SendRaw(fmt.Sprintf(`
|
||||||
|
<presence from='%s' to='%s' type='unavailable'>
|
||||||
|
<x xmlns='http://jabber.org/protocol/muc'/>
|
||||||
|
</presence>
|
||||||
|
`, clientroot.Session.BindJid, jid+"/"+tab.current_nick))
|
||||||
|
}
|
||||||
|
|
||||||
|
tabs.Delete(jid)
|
||||||
|
mucmembers.Delete(jid)
|
||||||
|
userdevices.Delete(jid)
|
||||||
|
|
||||||
|
if current == jid {
|
||||||
|
current = ""
|
||||||
|
scroller.SetChild(empty_dialog)
|
||||||
|
typingStatus.SetText("")
|
||||||
|
memberList.SetChild(gtk.NewLabel(""))
|
||||||
|
}
|
||||||
|
|
||||||
|
mucmembers.Delete(jid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func switchToTab(jid string, w *gtk.Window) {
|
func switchToTab(jid string, w *gtk.Window) {
|
||||||
current = jid
|
current = jid
|
||||||
tab, ok := tabs.Load(current)
|
tab, ok := tabs.Load(current)
|
||||||
@@ -160,7 +188,6 @@ func switchToTab(jid string, w *gtk.Window) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status := gtk.NewImageFromPaintable(clientAssets["status_"+string(u.Show)])
|
status := gtk.NewImageFromPaintable(clientAssets["status_"+string(u.Show)])
|
||||||
status.SetTooltipText(string(u.Show))
|
status.SetTooltipText(string(u.Show))
|
||||||
|
|
||||||
@@ -521,6 +548,7 @@ func switchToTab(jid string, w *gtk.Window) {
|
|||||||
gen.Prepend(muci)
|
gen.Prepend(muci)
|
||||||
muc_name := gtk.NewLabel(typed_tab.name)
|
muc_name := gtk.NewLabel(typed_tab.name)
|
||||||
muc_name.AddCSSClass("author")
|
muc_name.AddCSSClass("author")
|
||||||
|
muc_name.SetWrap(true)
|
||||||
gen.Prepend(muc_name)
|
gen.Prepend(muc_name)
|
||||||
memberList.SetChild(gen)
|
memberList.SetChild(gen)
|
||||||
} else {
|
} else {
|
||||||
@@ -529,7 +557,7 @@ func switchToTab(jid string, w *gtk.Window) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func showErrorDialog(err error) {
|
func showErrorDialog(err error, w *gtk.Window) {
|
||||||
err_win := gtk.NewWindow()
|
err_win := gtk.NewWindow()
|
||||||
err_win.SetTitle(loadedLocale["error"])
|
err_win.SetTitle(loadedLocale["error"])
|
||||||
err_win.SetDefaultSize(400, 200)
|
err_win.SetDefaultSize(400, 200)
|
||||||
@@ -546,6 +574,7 @@ func showErrorDialog(err error) {
|
|||||||
})
|
})
|
||||||
box.Append(close_btn)
|
box.Append(close_btn)
|
||||||
err_win.SetChild(box)
|
err_win.SetChild(box)
|
||||||
|
err_win.SetTransientFor(w)
|
||||||
err_win.Present()
|
err_win.Present()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
-31
@@ -92,46 +92,45 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter {
|
|||||||
popover.SetParent(mainBox)
|
popover.SetParent(mainBox)
|
||||||
popover.SetHasArrow(false)
|
popover.SetHasArrow(false)
|
||||||
|
|
||||||
|
|
||||||
gesture.Connect("pressed", func(n_press, x, y int) {
|
gesture.Connect("pressed", func(n_press, x, y int) {
|
||||||
rc_box := gtk.NewBox(gtk.OrientationVertical, 0)
|
rc_box := gtk.NewBox(gtk.OrientationVertical, 0)
|
||||||
|
|
||||||
reactions := gtk.NewBox(gtk.OrientationHorizontal, 0)
|
reactions := gtk.NewBox(gtk.OrientationHorizontal, 0)
|
||||||
reaction := []string{"👍", "👎", "♥️", "🤣", "💀"}
|
reaction := []string{"👍", "👎", "♥️", "🤣", "💀"}
|
||||||
for _, v := range reaction {
|
for _, v := range reaction {
|
||||||
like := gtk.NewButton()
|
like := gtk.NewButton()
|
||||||
like.SetLabel(v)
|
like.SetLabel(v)
|
||||||
like.SetHExpand(true)
|
like.SetHExpand(true)
|
||||||
like.ConnectClicked(func() {
|
like.ConnectClicked(func() {
|
||||||
fmt.Println("licked") // TODO: Implement proper support for reactions via extension
|
fmt.Println("licked") // TODO: Implement proper support for reactions via extension
|
||||||
client.SendRaw(fmt.Sprintf(`
|
client.SendRaw(fmt.Sprintf(`
|
||||||
<message from='%s' to='%s' id='%s' type='%s'>
|
<message from='%s' to='%s' id='%s' type='%s'>
|
||||||
<reactions id='%s' xmlns='urn:xmpp:reactions:0'>
|
<reactions id='%s' xmlns='urn:xmpp:reactions:0'>
|
||||||
<reaction>%s</reaction>
|
<reaction>%s</reaction>
|
||||||
</reactions>
|
</reactions>
|
||||||
</message>
|
</message>
|
||||||
`, m.To, jid.MustParse(m.From).Bare().String(), uuid.New().String(), m.Type, sid.ID, v))
|
`, m.To, jid.MustParse(m.From).Bare().String(), uuid.New().String(), m.Type, sid.ID, v))
|
||||||
})
|
})
|
||||||
reactions.Append(like)
|
reactions.Append(like)
|
||||||
}
|
|
||||||
|
|
||||||
rc_box.Append(reactions)
|
|
||||||
|
|
||||||
quote := gtk.NewButtonWithLabel("Quote")
|
|
||||||
quote.ConnectClicked(func() {
|
|
||||||
lines := strings.Split(m.Body, "\n")
|
|
||||||
for i, line := range lines {
|
|
||||||
quoteline := "> " + line
|
|
||||||
lines[i] = quoteline
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newstr := strings.Join(lines, "\n") + "\n\n"
|
rc_box.Append(reactions)
|
||||||
|
|
||||||
message_en.SetText(newstr)
|
quote := gtk.NewButtonWithLabel("Quote")
|
||||||
})
|
quote.ConnectClicked(func() {
|
||||||
rc_box.Append(quote)
|
lines := strings.Split(m.Body, "\n")
|
||||||
|
for i, line := range lines {
|
||||||
|
quoteline := "> " + line
|
||||||
|
lines[i] = quoteline
|
||||||
|
}
|
||||||
|
|
||||||
popover.SetChild(rc_box)
|
newstr := strings.Join(lines, "\n") + "\n\n"
|
||||||
|
|
||||||
|
message_en.SetText(newstr)
|
||||||
|
})
|
||||||
|
rc_box.Append(quote)
|
||||||
|
|
||||||
|
popover.SetChild(rc_box)
|
||||||
rect := gdk.NewRectangle(x, y, 1, 1)
|
rect := gdk.NewRectangle(x, y, 1, 1)
|
||||||
popover.SetPointingTo(&rect)
|
popover.SetPointingTo(&rect)
|
||||||
popover.Popup()
|
popover.Popup()
|
||||||
@@ -233,7 +232,6 @@ func generateMessageWidget(p stanza.Packet) gtk.Widgetter {
|
|||||||
mainBox.Append(authorBox)
|
mainBox.Append(authorBox)
|
||||||
mainBox.Append(contentBox)
|
mainBox.Append(contentBox)
|
||||||
|
|
||||||
|
|
||||||
oob := stanza.OOB{}
|
oob := stanza.OOB{}
|
||||||
ok = m.Get(&oob)
|
ok = m.Get(&oob)
|
||||||
if ok {
|
if ok {
|
||||||
@@ -315,7 +313,7 @@ func getAvatar(j, hash string) *gtk.Image { // TODO: This function probably shou
|
|||||||
invalidImages.Store(oghash, true)
|
invalidImages.Store(oghash, true)
|
||||||
return createIdenticon(j, false)
|
return createIdenticon(j, false)
|
||||||
}
|
}
|
||||||
i.AddCSSClass(loadedConfig.CVD.String() + "_CVD")
|
// i.AddCSSClass(loadedConfig.CVD.String() + "_CVD")
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +344,6 @@ func getAvatar(j, hash string) *gtk.Image { // TODO: This function probably shou
|
|||||||
|
|
||||||
base64_data := card.Photo.Binval
|
base64_data := card.Photo.Binval
|
||||||
if card.Photo.Binval == "" || ((card.Photo.Type == "image/svg+xml" || card.Photo.Type == "image/webp") && (runtime.GOOS == "windows" || runtime.GOOS == "netbsd")) {
|
if card.Photo.Binval == "" || ((card.Photo.Type == "image/svg+xml" || card.Photo.Type == "image/webp") && (runtime.GOOS == "windows" || runtime.GOOS == "netbsd")) {
|
||||||
fmt.Println("Blocking image")
|
|
||||||
invalidImages.Store(oghash, true)
|
invalidImages.Store(oghash, true)
|
||||||
return createIdenticon(j, false)
|
return createIdenticon(j, false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -325,6 +325,7 @@ func main() {
|
|||||||
ok = presence.Get(&mu)
|
ok = presence.Get(&mu)
|
||||||
|
|
||||||
if ok { // This is a presence stanza from a user in a MUC
|
if ok { // This is a presence stanza from a user in a MUC
|
||||||
|
|
||||||
presence.Get(&ocu)
|
presence.Get(&ocu)
|
||||||
// id := ocu.ID
|
// id := ocu.ID
|
||||||
// if id == "" {
|
// if id == "" {
|
||||||
@@ -333,7 +334,7 @@ func main() {
|
|||||||
from, _ := stanza.NewJid(presence.From)
|
from, _ := stanza.NewJid(presence.From)
|
||||||
muc := from.Bare()
|
muc := from.Bare()
|
||||||
_, ok = mucmembers.Load(muc)
|
_, ok = mucmembers.Load(muc)
|
||||||
if !ok {
|
if !ok && presence.Type != "unavailable" {
|
||||||
mucmembers.Store(muc, mucUnit{})
|
mucmembers.Store(muc, mucUnit{})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,6 +345,14 @@ func main() {
|
|||||||
|
|
||||||
typed_unit := unit.(mucUnit)
|
typed_unit := unit.(mucUnit)
|
||||||
|
|
||||||
|
if mu.MucUserItem.JID == clientroot.Session.BindJid {
|
||||||
|
tab, ok := tabs.Load(muc)
|
||||||
|
if ok {
|
||||||
|
typed_tab := tab.(*chatTab)
|
||||||
|
typed_tab.current_nick = id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if presence.Type != "unavailable" {
|
if presence.Type != "unavailable" {
|
||||||
_, ok := typed_unit.Members.Load(id)
|
_, ok := typed_unit.Members.Load(id)
|
||||||
if !ok && loadedConfig.ShowPresenceUpdates {
|
if !ok && loadedConfig.ShowPresenceUpdates {
|
||||||
@@ -408,7 +417,7 @@ func main() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
showErrorDialog(err)
|
showErrorDialog(err, &window.Window)
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
client = c
|
client = c
|
||||||
@@ -524,6 +533,13 @@ func main() {
|
|||||||
gesture1.Connect("pressed", func() {
|
gesture1.Connect("pressed", func() {
|
||||||
switchToTab(jid, &window.Window)
|
switchToTab(jid, &window.Window)
|
||||||
})
|
})
|
||||||
|
gesture2 := gtk.NewGestureClick()
|
||||||
|
gesture2.SetButton(3)
|
||||||
|
gesture2.Connect("pressed", func() {
|
||||||
|
removeTab(jid, &window.Window)
|
||||||
|
box.SetVisible(false)
|
||||||
|
})
|
||||||
|
|
||||||
box.Append(b)
|
box.Append(b)
|
||||||
go func() {
|
go func() {
|
||||||
new_im := getAvatar(jid, jid) // TODO: Use PEP avatar and do not use JID as hash
|
new_im := getAvatar(jid, jid) // TODO: Use PEP avatar and do not use JID as hash
|
||||||
@@ -604,6 +620,13 @@ func main() {
|
|||||||
gesture1.Connect("pressed", func() {
|
gesture1.Connect("pressed", func() {
|
||||||
switchToTab(jid, &window.Window)
|
switchToTab(jid, &window.Window)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
gesture2 := gtk.NewGestureClick()
|
||||||
|
gesture2.SetButton(3)
|
||||||
|
gesture2.Connect("pressed", func() {
|
||||||
|
removeTab(jid, &window.Window)
|
||||||
|
box.SetVisible(false)
|
||||||
|
})
|
||||||
box.Append(b)
|
box.Append(b)
|
||||||
go func() {
|
go func() {
|
||||||
new_im := getAvatar(jid, jid)
|
new_im := getAvatar(jid, jid)
|
||||||
@@ -614,6 +637,7 @@ func main() {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
box.AddController(gesture1)
|
box.AddController(gesture1)
|
||||||
|
box.AddController(gesture2)
|
||||||
menu.Append(box)
|
menu.Append(box)
|
||||||
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
|
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
|
||||||
})
|
})
|
||||||
@@ -840,7 +864,7 @@ func activate(app *gtk.Application) {
|
|||||||
jm := func(n string, pw string) {
|
jm := func(n string, pw string) {
|
||||||
err := joinMuc(client, clientroot.Session.BindJid, t, nick_entry.Text(), pw)
|
err := joinMuc(client, clientroot.Session.BindJid, t, nick_entry.Text(), pw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
showErrorDialog(err)
|
showErrorDialog(err, win)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -861,7 +885,15 @@ func activate(app *gtk.Application) {
|
|||||||
switchToTab(t, &window.Window)
|
switchToTab(t, &window.Window)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
gesture2 := gtk.NewGestureClick()
|
||||||
|
gesture2.SetButton(3)
|
||||||
|
gesture2.Connect("pressed", func() {
|
||||||
|
removeTab(t, &window.Window)
|
||||||
|
box.SetVisible(false)
|
||||||
|
})
|
||||||
|
|
||||||
box.AddController(gesture1)
|
box.AddController(gesture1)
|
||||||
|
box.AddController(gesture2)
|
||||||
menu.Append(box)
|
menu.Append(box)
|
||||||
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
|
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
|
||||||
}
|
}
|
||||||
@@ -999,9 +1031,9 @@ func activate(app *gtk.Application) {
|
|||||||
} else {
|
} else {
|
||||||
allowed = false
|
allowed = false
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
showErrorDialog(fmt.Errorf("%s: %s - %s", loadedLocale["discoFail"], result.Error.Reason, result.Error.Text))
|
showErrorDialog(fmt.Errorf("%s: %s - %s", loadedLocale["discoFail"], result.Error.Reason, result.Error.Text), win)
|
||||||
} else {
|
} else {
|
||||||
showErrorDialog(fmt.Errorf(loadedLocale["discoFail"]))
|
showErrorDialog(fmt.Errorf(loadedLocale["discoFail"]), win)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1227,7 +1259,7 @@ func activate(app *gtk.Application) {
|
|||||||
|
|
||||||
err := sendMessage(client, current, message_type, t, "", "", exts)
|
err := sendMessage(client, current, message_type, t, "", "", exts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
showErrorDialog(err)
|
showErrorDialog(err, &window.Window)
|
||||||
}
|
}
|
||||||
message_en.SetText("")
|
message_en.SetText("")
|
||||||
scrollToBottomAfterUpdate(scroller)
|
scrollToBottomAfterUpdate(scroller)
|
||||||
|
|||||||
@@ -7,22 +7,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type chatTab struct {
|
type chatTab struct {
|
||||||
isMuc bool
|
isMuc bool
|
||||||
msgs *gtk.ListBox
|
msgs *gtk.ListBox
|
||||||
name string
|
name string
|
||||||
|
current_nick string
|
||||||
}
|
}
|
||||||
|
|
||||||
type lambdaConfig struct {
|
type lambdaConfig struct {
|
||||||
Server string
|
Server string
|
||||||
Username string
|
Username string
|
||||||
Resource string
|
Resource string
|
||||||
Password string
|
Password string
|
||||||
Insecure bool
|
Insecure bool
|
||||||
Nick string
|
Nick string
|
||||||
JoinBookmarks bool
|
JoinBookmarks bool
|
||||||
CVD color.CVD
|
CVD color.CVD
|
||||||
Identicons bool
|
Identicons bool
|
||||||
Debug bool
|
Debug bool
|
||||||
ShowPresenceUpdates bool
|
ShowPresenceUpdates bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user