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) }