This repository has been archived on 2021-06-24. You can view files and clone it, but cannot push or open issues or pull requests.
ui/go/gothings/uistate.go

192 lines
5.2 KiB
Go

package gothings
import (
"cwtch.im/ui/go/constants"
"cwtch.im/ui/go/cwutil"
"cwtch.im/ui/go/gobjects"
"cwtch.im/ui/go/the"
"git.openprivacy.ca/openprivacy/libricochet-go/log"
"runtime/debug"
"sync"
"time"
)
type InterfaceState struct {
parentGcd *GrandCentralDispatcher
contacts sync.Map // string : *gobjects.Contact
messages sync.Map
}
func NewUIState(gcd *GrandCentralDispatcher) (uis InterfaceState) {
uis = InterfaceState{gcd, sync.Map{}, sync.Map{}}
return
}
func (this *InterfaceState) AddContact(c *gobjects.Contact) {
if len(c.Handle) == 32 { // ADD GROUP
if _, found := this.contacts.Load(c.Handle); !found {
this.parentGcd.AddContact(c.Handle, c.DisplayName, c.Image, c.Server, c.Badge, c.Status, c.Trusted, c.Loading)
this.contacts.Store(c.Handle, c)
}
return
} else if len(c.Handle) != 56 {
log.Errorf("sorry, unable to handle AddContact(%v)", c.Handle)
debug.PrintStack()
return
}
if _, found := this.contacts.Load(c.Handle); !found {
this.contacts.Store(c.Handle, c)
this.parentGcd.AddContact(c.Handle, c.DisplayName, c.Image, c.Server, c.Badge, c.Status, c.Trusted, false)
if the.Peer.GetContact(c.Handle) == nil {
the.Peer.AddContact(c.DisplayName, c.Handle, c.Trusted)
go the.Peer.PeerWithOnion(c.Handle)
}
}
}
func (this *InterfaceState) GetContact(handle string) *gobjects.Contact {
if _, found := this.contacts.Load(handle); !found {
if len(handle) == 32 {
group := the.Peer.GetGroup(handle)
if group != nil {
nick, exists := group.GetAttribute("nick")
if !exists {
nick = group.GroupID[:12]
}
this.AddContact(&gobjects.Contact{
handle,
nick,
cwutil.RandomGroupImage(handle),
group.GroupServer,
0,
0,
group.Accepted,
false,
})
go the.Peer.JoinServer(group.GroupServer)
} else {
log.Errorf("Attempting to add non existent group to ui %v", handle)
}
} else {
contact := the.Peer.GetContact(handle)
if contact != nil && handle != contact.Onion {
nick, exists := contact.GetAttribute("name")
if !exists {
nick = contact.Onion
}
this.AddContact(&gobjects.Contact{
handle,
nick,
cwutil.RandomProfileImage(handle),
"",
0,
0,
false,
false,
})
} else if contact == nil {
//log.Errorf("Attempting to add non existent contact to ui %v", handle)
}
}
}
contactIntf, _ := this.contacts.Load(handle)
if contactIntf == nil {
return nil
}
contact := contactIntf.(*gobjects.Contact)
return contact
}
func (this *InterfaceState) AddSendMessageError(peer string, signature string, err string) {
acklist := the.AcknowledgementIDs[peer]
for _, ack := range acklist {
if ack.ID == signature {
ack.Error = true
}
}
messages, _ := this.messages.Load(peer)
messageList, _ := messages.([]*gobjects.Message)
for _, message := range messageList {
if message.MessageID == signature {
message.Error = true
}
}
log.Debugf("Received Error Sending Message: %v", err)
// FIXME: Sometimes, for the first Peer message we send our error beats our message to the UI
time.Sleep(time.Second * 1)
this.parentGcd.GroupSendError(signature, err)
}
func (this *InterfaceState) AddMessage(m *gobjects.Message) {
this.GetContact(m.From)
_, found := this.messages.Load(m.Handle)
if !found {
this.messages.Store(m.Handle, make([]*gobjects.Message, 0))
}
// Ack message sent to group
this.parentGcd.Acknowledged(m.MessageID)
// Ack personal messages
// TODO: unify this with the above signature based approach
if m.Message == "ack" {
// If an ack, swallow the message and ack from the list.
acklist := the.AcknowledgementIDs[m.From]
for _, ack := range acklist {
if ack.Error == false {
ack.Ack = true
this.parentGcd.Acknowledged(ack.ID)
}
}
} else {
messages, _ := this.messages.Load(m.Handle)
messageList, _ := messages.([]*gobjects.Message)
this.messages.Store(m.Handle, append(messageList, m))
// If we have this group loaded already
if this.parentGcd.CurrentOpenConversation() == m.Handle {
// If the message is not from the user then add it, otherwise, just acknowledge.
if !m.FromMe || !m.Acknowledged {
this.parentGcd.AppendMessage(m.Handle, m.From, m.DisplayName, m.Message, m.Image, m.MessageID, m.FromMe, m.Timestamp.Format(constants.TIME_FORMAT), m.Acknowledged, m.Error)
} else {
this.parentGcd.Acknowledged(m.MessageID)
}
} else {
c := this.GetContact(m.Handle)
if c != nil {
c.Badge++
this.UpdateContact(c.Handle)
}
}
}
}
func (this *InterfaceState) GetMessages(handle string) []*gobjects.Message {
_, found := this.messages.Load(handle)
if !found {
this.messages.Store(handle, make([]*gobjects.Message, 0))
}
messages, found := this.messages.Load(handle)
messageList, _ := messages.([]*gobjects.Message)
return messageList
}
func (this *InterfaceState) UpdateContact(handle string) {
cif, found := this.contacts.Load(handle)
if found {
c := cif.(*gobjects.Contact)
this.parentGcd.UpdateContact(c.Handle, c.DisplayName, c.Image, c.Server, c.Badge, c.Status, c.Trusted, c.Loading)
}
}
func (this *InterfaceState) UpdateContactAttribute(handle, key, value string) {
this.parentGcd.UpdateContactAttribute(handle, key, value)
}