can we pretend that airplanes in the night sky are like shooting stars
This commit is contained in:
@@ -52,6 +52,9 @@ var tagBytes []byte
|
|||||||
//go:embed assets/lambda-disabled.png
|
//go:embed assets/lambda-disabled.png
|
||||||
var logoDisabledBytes []byte
|
var logoDisabledBytes []byte
|
||||||
|
|
||||||
|
//go:embed assets/icon.png
|
||||||
|
var logoBytes []byte
|
||||||
|
|
||||||
//go:embed assets/group.png
|
//go:embed assets/group.png
|
||||||
var groupBytes []byte
|
var groupBytes []byte
|
||||||
|
|
||||||
@@ -181,6 +184,7 @@ func clientAssetsLoad(key string) gdk.Paintabler {
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
for key, data := range map[string][]byte{
|
for key, data := range map[string][]byte{
|
||||||
|
"logo": logoBytes,
|
||||||
"DefaultAvatar": defaultAvatarBytes,
|
"DefaultAvatar": defaultAvatarBytes,
|
||||||
"FailedAvatar": failedBytes,
|
"FailedAvatar": failedBytes,
|
||||||
"owner": ownerMedalBytes,
|
"owner": ownerMedalBytes,
|
||||||
|
|||||||
@@ -265,6 +265,7 @@ func createTab(jid string, isMuc bool, name string) bool {
|
|||||||
})
|
})
|
||||||
newTab.name = name
|
newTab.name = name
|
||||||
newTab.msg_refsID = make(map[string]*abMessage)
|
newTab.msg_refsID = make(map[string]*abMessage)
|
||||||
|
newTab.msg_refsOSID = make(map[string]*abMessage)
|
||||||
tabs.Store(jid, newTab)
|
tabs.Store(jid, newTab)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-28
@@ -18,6 +18,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func generatePresenceWidget(p stanza.Packet) gtk.Widgetter {
|
func generatePresenceWidget(p stanza.Packet) gtk.Widgetter {
|
||||||
@@ -247,10 +248,6 @@ func generateMessageWidget(p stanza.Packet, blocked bool, target string) (gtk.Wi
|
|||||||
|
|
||||||
if loadedConfig.CompactMode {
|
if loadedConfig.CompactMode {
|
||||||
if m.Body == "" {
|
if m.Body == "" {
|
||||||
/*
|
|
||||||
mlabel.SetText(loadedLocale["noBodySet"])
|
|
||||||
mlabel.AddCSSClass("visitor")
|
|
||||||
*/
|
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
al := gtk.NewLabel(name)
|
al := gtk.NewLabel(name)
|
||||||
@@ -274,9 +271,20 @@ func generateMessageWidget(p stanza.Packet, blocked bool, target string) (gtk.Wi
|
|||||||
// mlabel.SetHAlign(gtk.AlignFill)
|
// mlabel.SetHAlign(gtk.AlignFill)
|
||||||
mainBox.Append(mlabel)
|
mainBox.Append(mlabel)
|
||||||
|
|
||||||
|
// TODO: Decouple this from widget generation
|
||||||
if store_label {
|
if store_label {
|
||||||
typed_tab.msg_refsID[m.Id].label_ref = mlabel
|
msg, ok := typed_tab.msg_refsID[m.Id]
|
||||||
tabs.Store(target, tab)
|
if !ok {
|
||||||
|
msg = new(abMessage)
|
||||||
|
typed_tab.msg_refsID[m.Id] = msg
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.label_ref = mlabel
|
||||||
|
msg.ocu_id = ocu.ID
|
||||||
|
|
||||||
|
if sid.ID != "" {
|
||||||
|
typed_tab.msg_refsOSID[sid.ID] = msg
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
authorBox := gtk.NewBox(gtk.OrientationHorizontal, 10)
|
authorBox := gtk.NewBox(gtk.OrientationHorizontal, 10)
|
||||||
@@ -318,11 +326,6 @@ func generateMessageWidget(p stanza.Packet, blocked bool, target string) (gtk.Wi
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
createIdenticon(m.From, false, im)
|
createIdenticon(m.From, false, im)
|
||||||
/*
|
|
||||||
im.SetPixelSize(40)
|
|
||||||
im.AddCSSClass("author_img")
|
|
||||||
authorBox.Append(im)
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
} else if m.Type == stanza.MessageTypeChat {
|
} else if m.Type == stanza.MessageTypeChat {
|
||||||
al.SetText(al.Text() + loadedLocale["whispers"])
|
al.SetText(al.Text() + loadedLocale["whispers"])
|
||||||
@@ -348,10 +351,6 @@ func generateMessageWidget(p stanza.Packet, blocked bool, target string) (gtk.Wi
|
|||||||
|
|
||||||
mlabel := gtk.NewLabel("")
|
mlabel := gtk.NewLabel("")
|
||||||
if m.Body == "" {
|
if m.Body == "" {
|
||||||
/*
|
|
||||||
mlabel.SetText(loadedLocale["noBodySet"])
|
|
||||||
mlabel.AddCSSClass("visitor")
|
|
||||||
*/
|
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,6 +359,7 @@ func generateMessageWidget(p stanza.Packet, blocked bool, target string) (gtk.Wi
|
|||||||
mlabel.SetSelectable(true)
|
mlabel.SetSelectable(true)
|
||||||
mlabel.SetHAlign(gtk.AlignFill)
|
mlabel.SetHAlign(gtk.AlignFill)
|
||||||
|
|
||||||
|
// TODO: Decouple this from widget generation
|
||||||
if store_label {
|
if store_label {
|
||||||
msg, ok := typed_tab.msg_refsID[m.Id]
|
msg, ok := typed_tab.msg_refsID[m.Id]
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -369,8 +369,12 @@ func generateMessageWidget(p stanza.Packet, blocked bool, target string) (gtk.Wi
|
|||||||
|
|
||||||
msg.label_ref = mlabel
|
msg.label_ref = mlabel
|
||||||
msg.ocu_id = ocu.ID
|
msg.ocu_id = ocu.ID
|
||||||
tabs.Store(target, typed_tab)
|
|
||||||
|
if sid.ID != "" {
|
||||||
|
typed_tab.msg_refsOSID[sid.ID] = msg
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
contentBox.Append(mlabel)
|
contentBox.Append(mlabel)
|
||||||
|
|
||||||
mainBox.Append(authorBox)
|
mainBox.Append(authorBox)
|
||||||
@@ -478,14 +482,6 @@ func getAvatar(j, hash string, i *gtk.Image) { // TODO: This function probably s
|
|||||||
|
|
||||||
_, err = os.ReadFile(hash)
|
_, err = os.ReadFile(hash)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
/*
|
|
||||||
i, err = newImageFromPath(hash)
|
|
||||||
if err != nil {
|
|
||||||
invalidImages.Store(oghash, true)
|
|
||||||
createIdenticon(j, false, i)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
glib.IdleAdd(func() {
|
glib.IdleAdd(func() {
|
||||||
setImageFromPath(hash, i)
|
setImageFromPath(hash, i)
|
||||||
})
|
})
|
||||||
@@ -506,12 +502,30 @@ func getAvatar(j, hash string, i *gtk.Image) { // TODO: This function probably s
|
|||||||
|
|
||||||
iqResp.Payload = &VCard{}
|
iqResp.Payload = &VCard{}
|
||||||
|
|
||||||
ctx := context.TODO()
|
ctx := context.Background()
|
||||||
mychan, err := client.SendIQ(ctx, iqResp)
|
timeoutctx, cancel := context.WithTimeout(ctx, time.Second*30)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
mychan, err := client.SendIQ(timeoutctx, iqResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
createIdenticon(j, false, i)
|
||||||
|
return
|
||||||
|
// panic(err)
|
||||||
}
|
}
|
||||||
result := <-mychan
|
|
||||||
|
var result stanza.IQ
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-timeoutctx.Done():
|
||||||
|
createIdenticon(j, false, i)
|
||||||
|
return
|
||||||
|
case result = <-mychan:
|
||||||
|
if result.Error != nil {
|
||||||
|
createIdenticon(j, false, i)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
card, ok := result.Payload.(*VCard)
|
card, ok := result.Payload.(*VCard)
|
||||||
if !ok {
|
if !ok {
|
||||||
createIdenticon(j, false, i)
|
createIdenticon(j, false, i)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"html"
|
"html"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
"github.com/diamondburned/gotk4/pkg/gtk/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -62,3 +63,13 @@ func XEPToPango(text string, correction bool) string {
|
|||||||
}
|
}
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GenerateRetraction(lab *gtk.Label, retraction Retraction) {
|
||||||
|
if retraction.Moderated.OccupantID.ID != "" {
|
||||||
|
lab.AddCSSClass("moderated")
|
||||||
|
lab.SetTooltipMarkup(fmt.Sprintf("<span weight='bold'>This message was <span foreground='magenta'>retracted</span> by a moderator.</span>\nReason: '%s'", html.EscapeString(retraction.Reason)))
|
||||||
|
} else {
|
||||||
|
lab.AddCSSClass("retracted")
|
||||||
|
lab.SetTooltipMarkup(fmt.Sprintf("<span weight='bold'>This message was retracted.</span>\nReason: '%s'", html.EscapeString(retraction.Reason)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
_ "net/http/pprof"
|
||||||
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -69,8 +73,6 @@ var styleCSS string
|
|||||||
var client xmpp.Sender
|
var client xmpp.Sender
|
||||||
var clientroot *xmpp.Client
|
var clientroot *xmpp.Client
|
||||||
|
|
||||||
var uiQueue = make(chan func(), 100)
|
|
||||||
|
|
||||||
var window *gtk.ApplicationWindow
|
var window *gtk.ApplicationWindow
|
||||||
|
|
||||||
// stores members of mucs
|
// stores members of mucs
|
||||||
@@ -88,20 +90,13 @@ var Roster = make(map[string]bool)
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
beeep.AppName = loadedLocale["appName"]
|
beeep.AppName = loadedLocale["appName"]
|
||||||
|
|
||||||
go func() {
|
|
||||||
for fn := range uiQueue {
|
|
||||||
glib.IdleAdd(func() bool {
|
|
||||||
fn()
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
time.Sleep(10 * time.Millisecond) // Small delay between updates
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
go func() {
|
||||||
|
log.Println(http.ListenAndServe("localhost:6060", nil))
|
||||||
|
}()
|
||||||
|
|
||||||
pingTimes = append(pingTimes, []float64{})
|
pingTimes = append(pingTimes, []float64{})
|
||||||
p, err := ensureConfig()
|
p, err := ensureConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -278,6 +273,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sid := new(StanzaID)
|
||||||
|
m.Get(sid)
|
||||||
|
|
||||||
originator := JidMustParse(m.From).Bare()
|
originator := JidMustParse(m.From).Bare()
|
||||||
|
|
||||||
glib.IdleAdd(func() {
|
glib.IdleAdd(func() {
|
||||||
@@ -364,6 +362,35 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The same, however with retractions
|
||||||
|
retraction := new(Retraction)
|
||||||
|
ok = m.Get(retraction)
|
||||||
|
if ok {
|
||||||
|
tab, ok := tabs.Load(originator)
|
||||||
|
if ok {
|
||||||
|
typed_tab := tab.(*chatTab)
|
||||||
|
/*
|
||||||
|
to_retract := ""
|
||||||
|
refs := typed_tab.msg_refsID
|
||||||
|
|
||||||
|
// If it is a DM, then we use regular message ID. If it is a MUC, we use stanza id
|
||||||
|
to_retract = sid.ID
|
||||||
|
if typed_tab.isMuc && sid != nil {
|
||||||
|
to_retract = sid.ID
|
||||||
|
refs = typed_tab.msg_refsOSID
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
msg, ok := typed_tab.msg_refsOSID[retraction.ID]
|
||||||
|
if ok {
|
||||||
|
lab := msg.label_ref
|
||||||
|
glib.IdleAdd(func() {
|
||||||
|
GenerateRetraction(lab, *retraction)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glib.IdleAdd(func() {
|
glib.IdleAdd(func() {
|
||||||
b := gtk.NewBox(gtk.OrientationVertical, 0)
|
b := gtk.NewBox(gtk.OrientationVertical, 0)
|
||||||
|
|
||||||
@@ -534,6 +561,7 @@ func main() {
|
|||||||
gStatus.SetText(fmt.Sprintf("%d goroutines", goroutines))
|
gStatus.SetText(fmt.Sprintf("%d goroutines", goroutines))
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
// Ping
|
// Ping
|
||||||
pingStatus.AddCSSClass("pending")
|
pingStatus.AddCSSClass("pending")
|
||||||
@@ -658,17 +686,8 @@ func main() {
|
|||||||
box.Append(im)
|
box.Append(im)
|
||||||
box.Append(b)
|
box.Append(b)
|
||||||
|
|
||||||
|
// TODO: Use PEP avatar and do not use JID as hash
|
||||||
go getAvatar(jid, jid, im)
|
go getAvatar(jid, jid, im)
|
||||||
/*
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
new_im := getAvatar(jid, jid) // TODO: Use PEP avatar and do not use JID as hash
|
|
||||||
glib.IdleAdd(func() {
|
|
||||||
new_im.SetPixelSize(40)
|
|
||||||
box.Prepend(new_im)
|
|
||||||
})
|
|
||||||
}()
|
|
||||||
*/
|
|
||||||
|
|
||||||
box.AddController(gesture1)
|
box.AddController(gesture1)
|
||||||
menu.Append(box)
|
menu.Append(box)
|
||||||
@@ -757,15 +776,6 @@ func main() {
|
|||||||
box.Prepend(im)
|
box.Prepend(im)
|
||||||
|
|
||||||
go getAvatar(jid, jid, im)
|
go getAvatar(jid, jid, im)
|
||||||
/*
|
|
||||||
go func() {
|
|
||||||
new_im := getAvatar(jid, jid)
|
|
||||||
glib.IdleAdd(func() {
|
|
||||||
new_im.SetPixelSize(40)
|
|
||||||
box.Prepend(new_im)
|
|
||||||
})
|
|
||||||
}()
|
|
||||||
*/
|
|
||||||
|
|
||||||
box.AddController(gesture1)
|
box.AddController(gesture1)
|
||||||
box.AddController(gesture2)
|
box.AddController(gesture2)
|
||||||
@@ -779,6 +789,41 @@ func main() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Local bookmarks
|
||||||
|
for jid, nick := range loadedConfig.LocalBookmarks {
|
||||||
|
joinMuc(client, clientroot.Session.BindJid, jid, nick, "")
|
||||||
|
createTab(jid, true, jid)
|
||||||
|
glib.IdleAdd(func() {
|
||||||
|
box := gtk.NewBox(gtk.OrientationHorizontal, 10)
|
||||||
|
b := gtk.NewLabel(jid)
|
||||||
|
gesture1 := gtk.NewGestureClick()
|
||||||
|
gesture1.SetButton(1)
|
||||||
|
gesture1.Connect("pressed", func() {
|
||||||
|
switchToTab(jid, &window.Window)
|
||||||
|
})
|
||||||
|
|
||||||
|
gesture2 := gtk.NewGestureClick()
|
||||||
|
gesture2.SetButton(3)
|
||||||
|
gesture2.Connect("pressed", func() {
|
||||||
|
removeTab(jid, &window.Window)
|
||||||
|
box.SetVisible(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
im := gtk.NewImage()
|
||||||
|
im.SetPixelSize(40)
|
||||||
|
|
||||||
|
box.Append(b)
|
||||||
|
box.Prepend(im)
|
||||||
|
|
||||||
|
go getAvatar(jid, jid, im)
|
||||||
|
|
||||||
|
box.AddController(gesture1)
|
||||||
|
box.AddController(gesture2)
|
||||||
|
menu.Append(box)
|
||||||
|
menu.Append(gtk.NewSeparator(gtk.OrientationHorizontal))
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -794,7 +839,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app := gtk.NewApplication("net.sunglocto.lambda", gio.ApplicationFlagsNone)
|
app := gtk.NewApplication("net.sunglocto.lambda", gio.ApplicationDefaultFlags)
|
||||||
app.ConnectActivate(func() {
|
app.ConnectActivate(func() {
|
||||||
activate(app)
|
activate(app)
|
||||||
go conc()
|
go conc()
|
||||||
@@ -886,22 +931,16 @@ func activate(app *gtk.Application) {
|
|||||||
about_window := gtk.NewWindow()
|
about_window := gtk.NewWindow()
|
||||||
about_window.SetTransientFor(&window.Window)
|
about_window.SetTransientFor(&window.Window)
|
||||||
about_window.SetTitle(fmt.Sprintf("%s %s", "About", loadedLocale["appName"]))
|
about_window.SetTitle(fmt.Sprintf("%s %s", "About", loadedLocale["appName"]))
|
||||||
a.SetProgramName("Lambda")
|
a.SetProgramName(loadedLocale["appName"])
|
||||||
a.SetVersion(lambda_version)
|
a.SetVersion(fmt.Sprintf("Version %s", lambda_version))
|
||||||
a.SetComments("yet another XMPP client")
|
a.SetComments("yet another XMPP client")
|
||||||
a.SetAuthors([]string{"Sunglocto"})
|
a.SetAuthors([]string{"Sunglocto", "Hydrogen", "Kuyuhi"})
|
||||||
a.SetLicense("GPL3")
|
a.SetLicenseType(gtk.LicenseGPL30)
|
||||||
|
a.SetLogo(clientAssetsLoad("logo"))
|
||||||
a.SetWebsite("https://forge.sunglocto.net/sunglocto/lambda")
|
a.SetWebsite("https://forge.sunglocto.net/sunglocto/lambda")
|
||||||
a.SetWebsiteLabel("Website")
|
a.SetWebsiteLabel("Website")
|
||||||
|
|
||||||
/*
|
a.SetVisible(true)
|
||||||
a.ConnectResponse(func() {
|
|
||||||
about_window.SetVisible(false)
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
about_window.SetChild(a)
|
|
||||||
about_window.SetDefaultSize(400, 300)
|
|
||||||
about_window.SetVisible(true)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
destroymucAction := gio.NewSimpleAction("destroymuc", nil)
|
destroymucAction := gio.NewSimpleAction("destroymuc", nil)
|
||||||
@@ -969,7 +1008,6 @@ func activate(app *gtk.Application) {
|
|||||||
if mu.MucUserItem.Affiliation != "owner" {
|
if mu.MucUserItem.Affiliation != "owner" {
|
||||||
box.Append(gtk.NewLabel(loadedLocale["destroyMUCNotOwnerWarning"]))
|
box.Append(gtk.NewLabel(loadedLocale["destroyMUCNotOwnerWarning"]))
|
||||||
}
|
}
|
||||||
// return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1042,7 +1080,7 @@ func activate(app *gtk.Application) {
|
|||||||
box.Append(bookmark_box)
|
box.Append(bookmark_box)
|
||||||
|
|
||||||
btn := gtk.NewButtonWithLabel(loadedLocale["submit"])
|
btn := gtk.NewButtonWithLabel(loadedLocale["submit"])
|
||||||
btn.SetVAlign(gtk.AlignBaseline)
|
btn.SetVAlign(gtk.AlignBaselineFill)
|
||||||
|
|
||||||
box.Append(btn)
|
box.Append(btn)
|
||||||
|
|
||||||
@@ -1332,11 +1370,7 @@ func activate(app *gtk.Application) {
|
|||||||
opt.Title = charts.TitleOption{
|
opt.Title = charts.TitleOption{
|
||||||
Text: loadedLocale["pingGraphTitle"],
|
Text: loadedLocale["pingGraphTitle"],
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
opt.XAxis.Labels = []string{
|
|
||||||
// The 7 labels here match to the 7 values above
|
|
||||||
"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun",
|
|
||||||
}*/
|
|
||||||
opt.Legend = charts.LegendOption{
|
opt.Legend = charts.LegendOption{
|
||||||
SeriesNames: []string{
|
SeriesNames: []string{
|
||||||
loadedLocale["pingGraphYAxis"],
|
loadedLocale["pingGraphYAxis"],
|
||||||
@@ -1383,17 +1417,6 @@ func activate(app *gtk.Application) {
|
|||||||
pBox.Append(pingStatus)
|
pBox.Append(pingStatus)
|
||||||
statBar.Append(pBox)
|
statBar.Append(pBox)
|
||||||
|
|
||||||
/*
|
|
||||||
sBox := gtk.NewBox(gtk.OrientationHorizontal, 0)
|
|
||||||
sIcon = gtk.NewImageFromPaintable(clientAssets["car"])
|
|
||||||
sIcon.AddCSSClass("icon")
|
|
||||||
sStatus = gtk.NewLabel("-")
|
|
||||||
sBox.Append(sIcon)
|
|
||||||
sBox.Append(sStatus)
|
|
||||||
sStatus.SetTooltipText(loadedLocale["throughputTooltip"])
|
|
||||||
statBar.Append(sBox)
|
|
||||||
*/
|
|
||||||
|
|
||||||
scrollerStatBar := gtk.NewScrolledWindow()
|
scrollerStatBar := gtk.NewScrolledWindow()
|
||||||
scrollerStatBar.SetChild(statBar)
|
scrollerStatBar.SetChild(statBar)
|
||||||
box.Append(scrollerStatBar)
|
box.Append(scrollerStatBar)
|
||||||
|
|||||||
@@ -30,6 +30,16 @@
|
|||||||
color: magenta;
|
color: magenta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.moderated {
|
||||||
|
color: magenta;
|
||||||
|
opacity: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.retracted {
|
||||||
|
color: grey;
|
||||||
|
opacity: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
.visitor {
|
.visitor {
|
||||||
color: grey;
|
color: grey;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ type chatTab struct {
|
|||||||
isMuc bool
|
isMuc bool
|
||||||
msgs *gtk.ListBox
|
msgs *gtk.ListBox
|
||||||
msg_refsID map[string]*abMessage
|
msg_refsID map[string]*abMessage
|
||||||
|
msg_refsOSID map[string]*abMessage
|
||||||
name string
|
name string
|
||||||
current_nick string
|
current_nick string
|
||||||
muc_presence *stanza.Presence
|
muc_presence *stanza.Presence
|
||||||
@@ -65,6 +66,9 @@ 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
|
||||||
|
|
||||||
|
// Local Bookmarks
|
||||||
|
LocalBookmarks map[string]string // key: JID, value: Nickname
|
||||||
|
|
||||||
// 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
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
var lambda_version string = "8"
|
var lambda_version string = "9"
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"gosrc.io/xmpp/stanza"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Implementation of XEP-0424: Message Retraction as well as XEP-0425: Moderated Message Retraction
|
||||||
|
|
||||||
|
type Retraction struct {
|
||||||
|
stanza.MsgExtension
|
||||||
|
XMLName xml.Name `xml:"urn:xmpp:message-retract:1 retract"`
|
||||||
|
ID string `xml:"id,attr"` // Stanza ID is used in group chats.
|
||||||
|
Reason string `xml:"reason"`
|
||||||
|
Moderated Moderated `xml:"urn:xmpp:message-moderate:1 moderated"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Moderated struct {
|
||||||
|
XMLName xml.Name `xml:"urn:xmpp:message-moderate:1 moderated"`
|
||||||
|
By string `xml:"by,attr"`
|
||||||
|
OccupantID OccupantID
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// To whoever thought putting the same element twice in the same message, but in different parents, and not specifying this behaviour anywhere in the XEP was a good idea, I want to kill you. Seriously, I do. If I see you walking home at night I will kill you. Brutally. Slowly. I will relish in the act. I will do it.
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{Space: "urn:xmpp:message-retract:1", Local: "retract"}, Retraction{})
|
||||||
|
}
|
||||||
@@ -14,6 +14,13 @@ type StanzaID struct {
|
|||||||
ID string `xml:"id,attr"`
|
ID string `xml:"id,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OriginID struct {
|
||||||
|
stanza.MsgExtension
|
||||||
|
XMLName xml.Name `xml:"urn:xmpp:sid:0 origin-id"`
|
||||||
|
ID string `xml:"id,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{Space: "urn:xmpp:sid:0", Local: "stanza-id"}, StanzaID{})
|
stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{Space: "urn:xmpp:sid:0", Local: "stanza-id"}, StanzaID{})
|
||||||
|
stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{Space: "urn:xmpp:sid:0", Local: "origin-id"}, OriginID{})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user