2018-11-22 00:01:17 +00:00
|
|
|
package gothings
|
|
|
|
|
|
|
|
import (
|
2019-01-21 21:41:47 +00:00
|
|
|
"cwtch.im/cwtch/event"
|
2018-11-28 22:14:02 +00:00
|
|
|
"cwtch.im/ui/go/constants"
|
|
|
|
"cwtch.im/ui/go/cwutil"
|
2019-03-18 23:52:46 +00:00
|
|
|
"github.com/therecipe/qt/qml"
|
2018-11-22 00:01:17 +00:00
|
|
|
|
2018-11-28 22:14:02 +00:00
|
|
|
"cwtch.im/ui/go/gobjects"
|
|
|
|
"cwtch.im/ui/go/the"
|
2018-11-22 00:01:17 +00:00
|
|
|
"encoding/base32"
|
2019-01-14 19:40:04 +00:00
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
2019-02-20 20:07:12 +00:00
|
|
|
"github.com/therecipe/qt/core"
|
2018-11-22 00:01:17 +00:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type GrandCentralDispatcher struct {
|
|
|
|
core.QObject
|
|
|
|
|
|
|
|
OutgoingMessages chan gobjects.Letter
|
2018-11-28 22:14:02 +00:00
|
|
|
UIState InterfaceState
|
2019-03-18 23:52:46 +00:00
|
|
|
QMLEngine *qml.QQmlApplicationEngine
|
|
|
|
Translator *core.QTranslator
|
2018-11-22 00:01:17 +00:00
|
|
|
|
2019-03-26 20:47:47 +00:00
|
|
|
_ string `property:"os"`
|
2018-11-22 00:01:17 +00:00
|
|
|
_ string `property:"currentOpenConversation"`
|
|
|
|
_ float32 `property:"themeScale"`
|
2019-03-27 19:57:11 +00:00
|
|
|
_ string `property:"version"`
|
|
|
|
_ string `property:"buildDate"`
|
2018-11-22 00:01:17 +00:00
|
|
|
|
|
|
|
// contact list stuff
|
|
|
|
_ func(handle, displayName, image, server string, badge, status int, trusted bool) `signal:"AddContact"`
|
|
|
|
_ func(handle, displayName, image, server string, badge, status int, trusted bool) `signal:"UpdateContact"`
|
2019-02-13 07:09:39 +00:00
|
|
|
_ func(handle, key, value string) `signal:"UpdateContactAttribute"`
|
2018-11-22 00:01:17 +00:00
|
|
|
|
|
|
|
// messages pane stuff
|
2019-03-05 20:16:27 +00:00
|
|
|
_ func(handle, from, displayName, message, image string, mID string, fromMe bool, ts string, ackd bool, error bool) `signal:"AppendMessage"`
|
2018-11-28 22:14:02 +00:00
|
|
|
_ func() `signal:"ClearMessages"`
|
|
|
|
_ func() `signal:"ResetMessagePane"`
|
2019-02-20 21:45:42 +00:00
|
|
|
_ func(mID string) `signal:"Acknowledged"`
|
2019-02-02 00:27:17 +00:00
|
|
|
_ func(title string) `signal:"SetToolbarTitle"`
|
2019-02-20 21:45:42 +00:00
|
|
|
_ func(signature string, err string) `signal:"GroupSendError"`
|
2018-11-22 00:01:17 +00:00
|
|
|
|
|
|
|
// profile-area stuff
|
|
|
|
_ func(name, onion, image string) `signal:"UpdateMyProfile"`
|
|
|
|
_ func(status int, str string) `signal:"TorStatus"`
|
|
|
|
|
2019-02-14 02:42:13 +00:00
|
|
|
// settings helpers
|
2019-02-05 00:41:18 +00:00
|
|
|
_ func(str string) `signal:"InvokePopup"`
|
2019-03-18 23:52:46 +00:00
|
|
|
_ func(zoom, locale string) `signal:"SupplySettings"`
|
2019-02-14 02:42:13 +00:00
|
|
|
_ func(groupID, name, server, invitation string, accepted bool, addrbooknames, addrbookaddrs []string) `signal:"SupplyGroupSettings"`
|
2019-02-05 00:41:18 +00:00
|
|
|
_ func(onion, nick string) `signal:"SupplyPeerSettings"`
|
2018-11-22 00:01:17 +00:00
|
|
|
|
|
|
|
// signals emitted from the ui (written in go, below)
|
2019-02-20 20:07:12 +00:00
|
|
|
_ func(message string, mid string) `signal:"sendMessage,auto"`
|
2018-11-22 00:01:17 +00:00
|
|
|
_ func(onion string) `signal:"loadMessagesPane,auto"`
|
|
|
|
_ func(signal string) `signal:"broadcast,auto"` // convenience relay signal
|
|
|
|
_ func(str string) `signal:"importString,auto"`
|
|
|
|
_ func(str string) `signal:"popup,auto"`
|
|
|
|
_ func(nick string) `signal:"updateNick,auto"`
|
|
|
|
_ func(server, groupName string) `signal:"createGroup,auto"`
|
2019-02-13 07:09:39 +00:00
|
|
|
_ func(groupID string) `signal:"leaveGroup,auto"`
|
2019-02-14 02:42:13 +00:00
|
|
|
_ func(groupID string) `signal:"acceptGroup,auto"`
|
2019-03-18 23:52:46 +00:00
|
|
|
_ func() `signal:"requestSettings,auto"`
|
|
|
|
_ func(zoom, locale string) `signal:"saveSettings,auto"`
|
2019-02-14 02:42:13 +00:00
|
|
|
_ func(groupID string) `signal:"requestGroupSettings,auto"`
|
2019-02-05 00:41:18 +00:00
|
|
|
_ func(groupID, nick string) `signal:"saveGroupSettings,auto"`
|
|
|
|
_ func() `signal:"requestPeerSettings,auto"`
|
|
|
|
_ func(onion, nick string) `signal:"savePeerSettings,auto"`
|
2019-02-11 20:23:31 +00:00
|
|
|
_ func(onion, groupID string) `signal:"inviteToGroup,auto"`
|
2019-02-13 07:09:39 +00:00
|
|
|
_ func(onion, key, nick string) `signal:"setAttribute,auto"`
|
2019-03-18 23:52:46 +00:00
|
|
|
_ func(locale string) `signal:"setLocale,auto"`
|
2018-11-22 00:01:17 +00:00
|
|
|
}
|
|
|
|
|
2019-02-20 20:07:12 +00:00
|
|
|
func (this *GrandCentralDispatcher) sendMessage(message string, mID string) {
|
2018-11-22 00:01:17 +00:00
|
|
|
if len(message) > 65530 {
|
|
|
|
this.InvokePopup("message is too long")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if this.CurrentOpenConversation() == "" {
|
|
|
|
this.InvokePopup("ui error")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(this.CurrentOpenConversation()) == 32 { // SEND TO GROUP
|
|
|
|
if !the.Peer.GetGroup(this.CurrentOpenConversation()).Accepted {
|
2019-01-28 19:57:44 +00:00
|
|
|
err := the.Peer.AcceptInvite(this.CurrentOpenConversation())
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("tried to mark a nonexistent group as existed. bad!")
|
|
|
|
return
|
|
|
|
}
|
2018-11-22 00:01:17 +00:00
|
|
|
c := this.UIState.GetContact(this.CurrentOpenConversation())
|
|
|
|
c.Trusted = true
|
|
|
|
this.UIState.UpdateContact(c.Handle)
|
|
|
|
}
|
|
|
|
|
2019-02-20 20:07:12 +00:00
|
|
|
var err error
|
|
|
|
mID,err = the.Peer.SendMessageToGroupTracked(this.CurrentOpenConversation(), message)
|
2019-03-04 22:02:11 +00:00
|
|
|
|
|
|
|
this.UIState.AddMessage(&gobjects.Message{
|
|
|
|
this.CurrentOpenConversation(),
|
|
|
|
"me",
|
|
|
|
"",
|
|
|
|
message,
|
|
|
|
"",
|
|
|
|
true,
|
|
|
|
mID,
|
|
|
|
time.Now(),
|
|
|
|
false,
|
2019-03-05 20:16:27 +00:00
|
|
|
false,
|
2019-03-04 22:02:11 +00:00
|
|
|
})
|
|
|
|
|
2019-02-20 20:07:12 +00:00
|
|
|
if err != nil {
|
|
|
|
this.InvokePopup("failed to send message " +err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
} else {
|
2018-11-22 00:01:17 +00:00
|
|
|
|
2019-02-20 20:07:12 +00:00
|
|
|
// TODO: require explicit invite accept/reject instead of implicitly trusting on send
|
|
|
|
if !this.UIState.GetContact(this.CurrentOpenConversation()).Trusted {
|
|
|
|
this.UIState.GetContact(this.CurrentOpenConversation()).Trusted = true
|
|
|
|
this.UIState.UpdateContact(this.CurrentOpenConversation())
|
|
|
|
}
|
2018-11-22 00:01:17 +00:00
|
|
|
|
2019-03-04 22:02:11 +00:00
|
|
|
to := this.CurrentOpenConversation();
|
|
|
|
the.Peer.PeerWithOnion(to)
|
|
|
|
mID = the.Peer.SendMessageToPeer(to, message)
|
|
|
|
|
|
|
|
this.UIState.AddMessage(&gobjects.Message{
|
2019-03-05 20:16:27 +00:00
|
|
|
to,
|
2019-03-04 22:02:11 +00:00
|
|
|
"me",
|
|
|
|
"",
|
|
|
|
message,
|
|
|
|
"",
|
|
|
|
true,
|
|
|
|
mID,
|
|
|
|
time.Now(),
|
|
|
|
false,
|
2019-03-05 20:16:27 +00:00
|
|
|
false,
|
2019-03-04 22:02:11 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
ackID := new(the.AckId)
|
|
|
|
ackID.ID = mID
|
|
|
|
ackID.Ack = false
|
|
|
|
the.AcknowledgementIDs[to] = append(the.AcknowledgementIDs[to], ackID)
|
2018-11-22 00:01:17 +00:00
|
|
|
}
|
|
|
|
|
2019-03-04 22:02:11 +00:00
|
|
|
|
2018-11-22 00:01:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (this *GrandCentralDispatcher) loadMessagesPane(handle string) {
|
2019-02-03 04:52:29 +00:00
|
|
|
go this.loadMessagesPaneHelper(handle)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) {
|
2018-11-22 00:01:17 +00:00
|
|
|
this.ClearMessages()
|
|
|
|
this.SetCurrentOpenConversation(handle)
|
|
|
|
c := this.UIState.GetContact(handle)
|
2019-02-05 21:09:38 +00:00
|
|
|
|
2019-02-13 07:09:39 +00:00
|
|
|
if c == nil {
|
|
|
|
this.UIState.AddContact(&gobjects.Contact{
|
|
|
|
handle,
|
|
|
|
handle,
|
|
|
|
cwutil.RandomProfileImage(handle),
|
|
|
|
"",
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
false,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
c.Badge = 0
|
|
|
|
this.UIState.UpdateContact(handle)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-11-22 00:01:17 +00:00
|
|
|
|
|
|
|
if len(handle) == 32 { // LOAD GROUP
|
2019-01-14 19:40:04 +00:00
|
|
|
log.Debugf("LOADING GROUP %s", handle)
|
2019-02-02 00:27:17 +00:00
|
|
|
group := the.Peer.GetGroup(handle)
|
|
|
|
tl := group.GetTimeline()
|
|
|
|
nick, _ := group.GetAttribute("nick")
|
|
|
|
if nick == "" {
|
|
|
|
this.SetToolbarTitle(handle)
|
|
|
|
} else {
|
|
|
|
this.SetToolbarTitle(nick)
|
|
|
|
}
|
2019-01-14 19:40:04 +00:00
|
|
|
log.Debugf("messages: %d", len(tl))
|
2018-11-22 00:01:17 +00:00
|
|
|
for i := range tl {
|
|
|
|
if tl[i].PeerID == the.Peer.GetProfile().Onion {
|
|
|
|
handle = "me"
|
|
|
|
} else {
|
|
|
|
handle = tl[i].PeerID
|
|
|
|
}
|
|
|
|
var name string
|
|
|
|
var exists bool
|
2019-02-05 00:41:18 +00:00
|
|
|
ctc := the.Peer.GetContact(tl[i].PeerID)
|
|
|
|
if ctc != nil {
|
|
|
|
name, exists = ctc.GetAttribute("nick")
|
|
|
|
if !exists || name == "" {
|
|
|
|
name = tl[i].PeerID[:16] + "..."
|
|
|
|
}
|
2018-11-22 00:01:17 +00:00
|
|
|
}
|
|
|
|
this.AppendMessage(
|
|
|
|
handle,
|
|
|
|
tl[i].PeerID,
|
|
|
|
name,
|
|
|
|
tl[i].Message,
|
|
|
|
cwutil.RandomProfileImage(tl[i].PeerID),
|
2019-02-20 20:07:12 +00:00
|
|
|
string(tl[i].Signature),
|
2018-11-22 00:01:17 +00:00
|
|
|
tl[i].PeerID == the.Peer.GetProfile().Onion,
|
|
|
|
tl[i].Timestamp.Format(constants.TIME_FORMAT),
|
2019-02-20 20:07:12 +00:00
|
|
|
tl[i].Received.Equal(time.Unix(0,0)) == false, // If the received timestamp is epoch, we have not yet received this message through an active server
|
2019-03-05 20:16:27 +00:00
|
|
|
false,
|
|
|
|
)
|
2018-11-22 00:01:17 +00:00
|
|
|
}
|
|
|
|
return
|
|
|
|
} // ELSE LOAD CONTACT
|
|
|
|
|
2019-02-03 00:04:41 +00:00
|
|
|
contact, _ := the.Peer.GetProfile().GetContact(handle)
|
2019-02-13 03:08:23 +00:00
|
|
|
if contact != nil {
|
|
|
|
nick, _ := contact.GetAttribute("nick")
|
|
|
|
if nick == "" {
|
|
|
|
this.SetToolbarTitle(handle)
|
|
|
|
} else {
|
|
|
|
this.SetToolbarTitle(nick)
|
|
|
|
}
|
2019-02-02 00:27:17 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 00:01:17 +00:00
|
|
|
messages := this.UIState.GetMessages(handle)
|
|
|
|
for i := range messages {
|
|
|
|
from := messages[i].From
|
|
|
|
if messages[i].FromMe {
|
|
|
|
from = "me"
|
|
|
|
}
|
2019-03-05 20:16:27 +00:00
|
|
|
|
2018-11-22 00:01:17 +00:00
|
|
|
this.AppendMessage(
|
|
|
|
messages[i].Handle,
|
|
|
|
from,
|
|
|
|
messages[i].DisplayName,
|
|
|
|
messages[i].Message,
|
|
|
|
cwutil.RandomProfileImage(handle),
|
2019-02-20 20:07:12 +00:00
|
|
|
messages[i].MessageID,
|
2018-11-22 00:01:17 +00:00
|
|
|
messages[i].FromMe,
|
|
|
|
messages[i].Timestamp.Format(constants.TIME_FORMAT),
|
2019-03-05 20:16:27 +00:00
|
|
|
false,
|
|
|
|
messages[i].Error,
|
2018-11-22 00:01:17 +00:00
|
|
|
)
|
2019-02-11 21:05:01 +00:00
|
|
|
for _,id := range the.AcknowledgementIDs[messages[i].Handle] {
|
2019-03-05 20:16:27 +00:00
|
|
|
if id.ID == messages[i].MessageID && id.Ack && !id.Error {
|
2019-02-11 21:05:01 +00:00
|
|
|
this.Acknowledged(id.ID)
|
|
|
|
}
|
|
|
|
}
|
2018-11-22 00:01:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-18 23:52:46 +00:00
|
|
|
func (this *GrandCentralDispatcher) requestSettings() {
|
|
|
|
zoom, _ := the.Peer.GetProfile().GetAttribute("settings.zoom")
|
|
|
|
locale, _ := the.Peer.GetProfile().GetAttribute("settings.locale")
|
|
|
|
this.SupplySettings(zoom, locale)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *GrandCentralDispatcher) saveSettings(zoom, locale string) {
|
|
|
|
// saveSettings accidentally gets called once when the app first starts but before the app has been prepared
|
|
|
|
// so let's just ignore that one
|
|
|
|
if the.CwtchApp == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetAttribute, map[event.Field]string{
|
|
|
|
event.Key: "settings.zoom",
|
|
|
|
event.Data: zoom,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2019-02-05 00:41:18 +00:00
|
|
|
func (this *GrandCentralDispatcher) requestPeerSettings() {
|
|
|
|
contact := the.Peer.GetContact(this.CurrentOpenConversation())
|
|
|
|
if contact == nil {
|
|
|
|
log.Errorf("error: requested settings for unknown contact %v?", this.CurrentOpenConversation())
|
|
|
|
this.SupplyPeerSettings(this.CurrentOpenConversation(), this.CurrentOpenConversation())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
name, exists := contact.GetAttribute("nick")
|
|
|
|
if !exists {
|
|
|
|
log.Errorf("error: couldn't find contact %v", this.CurrentOpenConversation())
|
|
|
|
this.SupplyPeerSettings(this.CurrentOpenConversation(), this.CurrentOpenConversation())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
this.SupplyPeerSettings(contact.Onion, name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *GrandCentralDispatcher) savePeerSettings(onion, nick string) {
|
|
|
|
contact := the.Peer.GetContact(onion)
|
|
|
|
if contact == nil {
|
|
|
|
log.Errorf("error: tried to save settings for unknown peer %v", onion)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
contact.SetAttribute("nick", nick)
|
|
|
|
the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetPeerAttribute, map[event.Field]string{
|
|
|
|
event.RemotePeer: onion,
|
|
|
|
event.Key: "nick",
|
|
|
|
event.Data: nick,
|
|
|
|
}))
|
|
|
|
|
|
|
|
this.UIState.contacts[onion].DisplayName = nick
|
|
|
|
this.UIState.UpdateContact(onion)
|
|
|
|
}
|
|
|
|
|
2019-02-14 02:42:13 +00:00
|
|
|
func (this *GrandCentralDispatcher) requestGroupSettings(groupID string) {
|
|
|
|
group := the.Peer.GetGroup(groupID)
|
2019-01-14 19:40:04 +00:00
|
|
|
|
|
|
|
if group == nil {
|
2019-02-14 02:42:13 +00:00
|
|
|
log.Errorf("couldn't find group %v", groupID)
|
2019-01-14 19:40:04 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-11-22 00:01:17 +00:00
|
|
|
nick, _ := group.GetAttribute("nick")
|
2019-02-14 02:42:13 +00:00
|
|
|
invite, _ := the.Peer.ExportGroup(groupID)
|
2019-02-11 20:23:31 +00:00
|
|
|
|
|
|
|
contactaddrs := the.Peer.GetContacts()
|
|
|
|
contactnames := make([]string, len(contactaddrs))
|
|
|
|
for i, contact := range contactaddrs {
|
|
|
|
name, hasname := the.Peer.GetContact(contact).GetAttribute("nick")
|
|
|
|
if hasname {
|
|
|
|
contactnames[i] = name
|
|
|
|
} else {
|
|
|
|
contactnames[i] = contact
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-14 02:42:13 +00:00
|
|
|
this.SupplyGroupSettings(group.GroupID, nick, group.GroupServer, invite, group.Accepted, contactnames, contactaddrs)
|
2019-02-05 00:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (this *GrandCentralDispatcher) saveGroupSettings(groupID, nick string) {
|
2019-02-13 07:09:39 +00:00
|
|
|
group := the.Peer.GetGroup(groupID)
|
2019-02-05 00:41:18 +00:00
|
|
|
|
|
|
|
if group == nil {
|
|
|
|
log.Errorf("couldn't find group %v", groupID)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
group.SetAttribute("nick", nick)
|
|
|
|
the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetGroupAttribute, map[event.Field]string{
|
|
|
|
event.GroupID: groupID,
|
|
|
|
event.Key: "nick",
|
|
|
|
event.Data: nick,
|
|
|
|
}))
|
|
|
|
|
|
|
|
this.UIState.contacts[groupID].DisplayName = nick
|
|
|
|
this.UIState.UpdateContact(groupID)
|
2018-11-22 00:01:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (this *GrandCentralDispatcher) broadcast(signal string) {
|
|
|
|
switch signal {
|
|
|
|
default:
|
2019-01-14 19:40:04 +00:00
|
|
|
log.Debugf("unhandled broadcast signal: %v", signal)
|
2018-11-22 00:01:17 +00:00
|
|
|
case "ResetMessagePane":
|
|
|
|
this.ResetMessagePane()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *GrandCentralDispatcher) importString(str string) {
|
|
|
|
if len(str) < 5 {
|
2019-01-14 19:40:04 +00:00
|
|
|
log.Debugf("ignoring short string")
|
2018-11-22 00:01:17 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-01-14 19:40:04 +00:00
|
|
|
log.Debugf("importing: %s\n", str)
|
2018-11-22 00:01:17 +00:00
|
|
|
onion := str
|
|
|
|
name := onion
|
|
|
|
str = strings.TrimSpace(str)
|
|
|
|
|
|
|
|
//eg: torv3JFDWkXExBsZLkjvfkkuAxHsiLGZBk0bvoeJID9ItYnU=EsEBCiBhOWJhZDU1OTQ0NWI3YmM2N2YxYTM5YjkzMTNmNTczNRIgpHeNaG+6jy750eDhwLO39UX4f2xs0irK/M3P6mDSYQIaOTJjM2ttb29ibnlnaGoyenc2cHd2N2Q1N3l6bGQ3NTNhdW8zdWdhdWV6enB2ZmFrM2FoYzRiZHlkCiJAdVSSVgsksceIfHe41OJu9ZFHO8Kwv3G6F5OK3Hw4qZ6hn6SiZjtmJlJezoBH0voZlCahOU7jCOg+dsENndZxAA==
|
|
|
|
if str[0:5] == "torv3" { // GROUP INVITE
|
2019-02-13 03:08:23 +00:00
|
|
|
_, err := the.Peer.ImportGroup(str)
|
2018-11-22 00:01:17 +00:00
|
|
|
if err != nil {
|
|
|
|
this.InvokePopup("not a valid group invite")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if strings.Contains(str, " ") { // usually people prepend spaces and we don't want it going into the name (use ~ for that)
|
|
|
|
parts := strings.Split(strings.TrimSpace(str), " ")
|
|
|
|
str = parts[len(parts)-1]
|
|
|
|
}
|
|
|
|
|
|
|
|
if strings.Contains(str, "~") {
|
|
|
|
parts := strings.Split(str, "~")
|
|
|
|
onion = parts[len(parts)-1]
|
|
|
|
name = strings.Join(parts[:len(parts)-1], " ")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(onion) != 56 {
|
|
|
|
this.InvokePopup("invalid format")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
name = strings.TrimSpace(name)
|
|
|
|
if name == "" {
|
|
|
|
this.InvokePopup("empty name")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(name) > 32 {
|
|
|
|
name = name[:32] //TODO: better strategy for long names?
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := base32.StdEncoding.DecodeString(strings.ToUpper(onion[:56]))
|
|
|
|
if err != nil {
|
2018-12-05 16:05:39 +00:00
|
|
|
log.Debugln(err)
|
2018-11-22 00:01:17 +00:00
|
|
|
this.InvokePopup("bad format. missing characters?")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-02-05 00:41:18 +00:00
|
|
|
checkc := the.Peer.GetContact(onion)
|
|
|
|
if checkc != nil {
|
2019-02-13 07:09:39 +00:00
|
|
|
deleted,_ := checkc.GetAttribute("deleted")
|
|
|
|
if deleted != "deleted" {
|
|
|
|
this.InvokePopup("already have this contact")
|
|
|
|
return //TODO: bring them to the duplicate
|
|
|
|
}
|
|
|
|
this.SetAttribute(onion, "deleted", "")
|
2018-11-22 00:01:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
this.UIState.AddContact(&gobjects.Contact{
|
2019-01-21 21:17:51 +00:00
|
|
|
Handle: onion,
|
|
|
|
DisplayName: name,
|
|
|
|
Image: cwutil.RandomProfileImage(onion),
|
|
|
|
Trusted: true,
|
2018-11-22 00:01:17 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *GrandCentralDispatcher) popup(str string) {
|
|
|
|
this.InvokePopup(str)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *GrandCentralDispatcher) updateNick(nick string) {
|
|
|
|
the.Peer.GetProfile().Name = nick
|
2019-01-28 19:57:44 +00:00
|
|
|
the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetProfileName, map[event.Field]string{
|
|
|
|
event.ProfileName: nick,
|
|
|
|
}))
|
2018-11-22 00:01:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (this *GrandCentralDispatcher) createGroup(server, groupName string) {
|
|
|
|
groupID, _, err := the.Peer.StartGroup(server)
|
|
|
|
if err != nil {
|
|
|
|
this.popup("group creation failed :(")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
this.UIState.AddContact(&gobjects.Contact{
|
2019-01-21 21:17:51 +00:00
|
|
|
Handle: groupID,
|
|
|
|
DisplayName: groupName,
|
|
|
|
Image: cwutil.RandomGroupImage(groupID),
|
|
|
|
Server: server,
|
|
|
|
Trusted: true,
|
2018-11-22 00:01:17 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
group := the.Peer.GetGroup(groupID)
|
2019-02-14 02:53:36 +00:00
|
|
|
group.SetAttribute("nick", groupName)
|
2019-01-28 19:57:44 +00:00
|
|
|
the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetGroupAttribute, map[event.Field]string{
|
|
|
|
event.GroupID: groupID,
|
|
|
|
event.Key: "nick",
|
|
|
|
event.Data: groupName,
|
|
|
|
}))
|
2018-11-22 00:01:17 +00:00
|
|
|
|
|
|
|
the.Peer.JoinServer(server)
|
2018-11-28 22:14:02 +00:00
|
|
|
}
|
2019-02-11 20:23:31 +00:00
|
|
|
|
|
|
|
func (this *GrandCentralDispatcher) inviteToGroup(onion, groupID string) {
|
|
|
|
err := the.Peer.InviteOnionToGroup(onion, groupID)
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("inviting %v to %v: %v", onion, groupID, err)
|
|
|
|
}
|
2019-02-13 07:09:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (this *GrandCentralDispatcher) leaveGroup(groupID string) {
|
|
|
|
the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetGroupAttribute, map[event.Field]string{
|
|
|
|
event.GroupID: groupID,
|
|
|
|
event.Key: "deleted",
|
|
|
|
event.Data: "deleted",
|
|
|
|
}))
|
|
|
|
this.UIState.UpdateContactAttribute(groupID, "deleted", "deleted")
|
|
|
|
}
|
|
|
|
|
2019-02-14 02:42:13 +00:00
|
|
|
func (this *GrandCentralDispatcher) acceptGroup(groupID string) {
|
|
|
|
if the.Peer.GetGroup(groupID) != nil {
|
|
|
|
the.Peer.AcceptInvite(groupID)
|
|
|
|
the.Peer.JoinServer(the.Peer.GetGroup(groupID).GroupServer)
|
|
|
|
this.UIState.UpdateContact(groupID)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-13 07:09:39 +00:00
|
|
|
func (this *GrandCentralDispatcher) setAttribute(onion, key, value string) {
|
|
|
|
pp,_ := the.Peer.GetProfile().GetContact(onion)
|
|
|
|
if pp != nil {
|
|
|
|
pp.SetAttribute(key, value)
|
|
|
|
the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetPeerAttribute, map[event.Field]string{
|
|
|
|
event.RemotePeer: onion,
|
|
|
|
event.Key: key,
|
|
|
|
event.Data: value,
|
|
|
|
}))
|
|
|
|
this.UIState.UpdateContactAttribute(onion, key, value)
|
|
|
|
}
|
2019-03-18 23:52:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (this *GrandCentralDispatcher) setLocale(locale string) {
|
|
|
|
this.SetLocale_helper(locale)
|
|
|
|
|
|
|
|
the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetAttribute, map[event.Field]string{
|
|
|
|
event.Key: "settings.locale",
|
|
|
|
event.Data: locale,
|
|
|
|
}))
|
|
|
|
|
|
|
|
this.SupplySettings("", locale)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *GrandCentralDispatcher) SetLocale_helper(locale string) {
|
|
|
|
core.QCoreApplication_RemoveTranslator(this.Translator)
|
|
|
|
this.Translator = core.NewQTranslator(nil)
|
|
|
|
this.Translator.Load("translation_"+locale, ":/i18n/", "", "")
|
|
|
|
core.QCoreApplication_InstallTranslator(this.Translator)
|
|
|
|
this.QMLEngine.Retranslate()
|
2019-02-11 20:23:31 +00:00
|
|
|
}
|