2019-11-08 21:34:12 +00:00
|
|
|
package ui
|
2018-11-22 00:01:17 +00:00
|
|
|
|
|
|
|
import (
|
2019-10-25 19:26:25 +00:00
|
|
|
"cwtch.im/cwtch/model"
|
2019-11-02 00:40:06 +00:00
|
|
|
"cwtch.im/cwtch/protocol/connections"
|
2018-11-28 22:14:02 +00:00
|
|
|
"cwtch.im/ui/go/constants"
|
|
|
|
"cwtch.im/ui/go/the"
|
2018-12-05 16:05:39 +00:00
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
2019-02-04 23:00:12 +00:00
|
|
|
"runtime/debug"
|
2019-03-05 20:16:27 +00:00
|
|
|
"time"
|
2018-11-22 00:01:17 +00:00
|
|
|
)
|
|
|
|
|
2019-11-02 00:40:06 +00:00
|
|
|
func isGroup(id string) bool {
|
|
|
|
return len(id) == 32
|
2019-10-25 19:26:25 +00:00
|
|
|
}
|
|
|
|
|
2019-11-02 00:40:06 +00:00
|
|
|
func isPeer(id string) bool {
|
|
|
|
return len(id) == 56
|
|
|
|
}
|
|
|
|
|
2019-11-08 21:34:12 +00:00
|
|
|
func getOrDefault(id, key, defaultVal string) string {
|
|
|
|
var val string
|
|
|
|
var ok bool
|
|
|
|
if isGroup(id) {
|
|
|
|
val, ok = the.Peer.GetGroupAttribute(id, key)
|
|
|
|
} else {
|
|
|
|
val, ok = the.Peer.GetContactAttribute(id, key)
|
|
|
|
}
|
|
|
|
if ok {
|
|
|
|
return val
|
|
|
|
} else {
|
|
|
|
return defaultVal
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-02 00:40:06 +00:00
|
|
|
func getWithSetDefault(id string, key, defaultVal string) string {
|
|
|
|
var val string
|
|
|
|
var ok bool
|
|
|
|
if isGroup(id) {
|
|
|
|
val, ok = the.Peer.GetGroupAttribute(id, key)
|
2019-10-25 19:26:25 +00:00
|
|
|
} else {
|
2019-11-02 00:40:06 +00:00
|
|
|
val, ok = the.Peer.GetContactAttribute(id, key)
|
2019-10-25 19:26:25 +00:00
|
|
|
}
|
2019-11-02 00:40:06 +00:00
|
|
|
if !ok {
|
|
|
|
val = defaultVal
|
|
|
|
if isGroup(id) {
|
|
|
|
the.Peer.SetGroupAttribute(id, key, defaultVal)
|
|
|
|
} else {
|
|
|
|
the.Peer.SetContactAttribute(id, key, defaultVal)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return val
|
|
|
|
}
|
|
|
|
|
|
|
|
// initLastReadTime checks and gets the Attributable's LastRead time or sets it to now
|
|
|
|
func initLastReadTime(id string) time.Time {
|
|
|
|
nowStr, _ := time.Now().MarshalText()
|
|
|
|
lastReadStr := getWithSetDefault(id, constants.LastRead, string(nowStr))
|
|
|
|
var lastRead time.Time
|
|
|
|
lastRead.UnmarshalText([]byte(lastReadStr))
|
2019-10-25 19:26:25 +00:00
|
|
|
return lastRead
|
|
|
|
}
|
|
|
|
|
2019-11-02 00:40:06 +00:00
|
|
|
func initProfilePicture(id string) string {
|
|
|
|
if isGroup(id) {
|
2019-11-08 21:34:12 +00:00
|
|
|
return getWithSetDefault(id, constants.Picture, RandomGroupImage(id))
|
2019-11-02 00:40:06 +00:00
|
|
|
} else {
|
2019-11-08 21:34:12 +00:00
|
|
|
return getWithSetDefault(id, constants.Picture, RandomProfileImage(id))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// getProfilePic supplies a profile pic to use. In groups we may not have a contact so it will generate one
|
|
|
|
func getProfilePic(id string) string {
|
|
|
|
if isGroup(id) {
|
|
|
|
if pic, exists := the.Peer.GetGroupAttribute(id, constants.Picture); !exists {
|
|
|
|
return RandomGroupImage(id)
|
|
|
|
} else {
|
|
|
|
return pic
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if pic, exists := the.Peer.GetContactAttribute(id, constants.Picture); !exists {
|
|
|
|
return RandomProfileImage(id)
|
|
|
|
} else {
|
|
|
|
return pic
|
|
|
|
}
|
2019-11-02 00:40:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func updateLastReadTime(id string) {
|
|
|
|
lastRead, _ := time.Now().MarshalText()
|
|
|
|
if isGroup(id) {
|
|
|
|
the.Peer.SetGroupAttribute(id, constants.LastRead, string(lastRead))
|
|
|
|
} else {
|
|
|
|
the.Peer.SetContactAttribute(id, constants.LastRead, string(lastRead))
|
|
|
|
}
|
2019-10-25 19:26:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func countUnread(messages []model.Message, lastRead time.Time) int {
|
|
|
|
count := 0
|
|
|
|
for i := len(messages) - 1; i >= 0; i-- {
|
2019-10-22 18:55:16 +00:00
|
|
|
if messages[i].Timestamp.After(lastRead) || messages[i].Timestamp.Equal(lastRead) {
|
2019-10-25 19:26:25 +00:00
|
|
|
count++
|
|
|
|
} else {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count
|
|
|
|
}
|
|
|
|
|
2019-11-08 21:34:12 +00:00
|
|
|
type Manager struct {
|
|
|
|
gcd *GrandCentralDispatcher
|
2018-11-22 00:01:17 +00:00
|
|
|
}
|
|
|
|
|
2019-11-08 21:34:12 +00:00
|
|
|
func NewManager(gcd *GrandCentralDispatcher) Manager {
|
|
|
|
return Manager{gcd}
|
2018-11-22 00:01:17 +00:00
|
|
|
}
|
|
|
|
|
2019-10-22 18:55:16 +00:00
|
|
|
func (this *Manager) AddProfile(handle string) {
|
|
|
|
peer := the.CwtchApp.GetPeer(handle)
|
|
|
|
if peer != nil {
|
|
|
|
nick := peer.GetProfile().Name
|
|
|
|
if nick == "" {
|
|
|
|
nick = handle
|
|
|
|
peer.SetAttribute(constants.Nick, nick)
|
|
|
|
}
|
|
|
|
|
|
|
|
pic, ok := peer.GetAttribute(constants.Picture)
|
|
|
|
if !ok {
|
|
|
|
pic = RandomProfileImage(handle)
|
|
|
|
peer.SetAttribute(constants.Picture, pic)
|
|
|
|
}
|
|
|
|
log.Infof("AddProfile %v %v %v\n", handle, nick, pic)
|
|
|
|
this.gcd.AddProfile(handle, nick, pic)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-08 21:34:12 +00:00
|
|
|
func (this *Manager) Acknowledge(mID string) {
|
|
|
|
this.gcd.Acknowledged(mID)
|
2019-07-31 18:59:43 +00:00
|
|
|
}
|
|
|
|
|
2019-11-15 01:13:42 +00:00
|
|
|
func getLastMessageTime(tl *model.Timeline) int {
|
|
|
|
if len(tl.Messages) == 0 {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
return int(tl.Messages[len(tl.Messages)-1].Timestamp.Unix())
|
|
|
|
}
|
|
|
|
|
2019-11-08 21:34:12 +00:00
|
|
|
func (this *Manager) AddContact(Handle string) {
|
2019-11-02 00:40:06 +00:00
|
|
|
if isGroup(Handle) {
|
|
|
|
group := the.Peer.GetGroup(Handle)
|
2019-10-25 19:26:25 +00:00
|
|
|
if group != nil {
|
2019-11-02 00:40:06 +00:00
|
|
|
lastRead := initLastReadTime(group.GroupID)
|
|
|
|
unread := countUnread(group.Timeline.GetMessages(), lastRead)
|
|
|
|
picture := initProfilePicture(Handle)
|
|
|
|
nick, exists := group.GetAttribute(constants.Nick)
|
|
|
|
if !exists {
|
|
|
|
nick = Handle
|
|
|
|
}
|
|
|
|
|
2019-11-15 01:13:42 +00:00
|
|
|
this.gcd.AddContact(Handle, nick, picture, group.GroupServer, unread, int(connections.ConnectionStateToType[group.State]), false, false, getLastMessageTime(&group.Timeline))
|
2018-11-22 00:01:17 +00:00
|
|
|
}
|
|
|
|
return
|
2019-11-02 00:40:06 +00:00
|
|
|
} else if !isPeer(Handle) {
|
|
|
|
log.Errorf("sorry, unable to handle AddContact(%v)", Handle)
|
2019-02-04 23:00:12 +00:00
|
|
|
debug.PrintStack()
|
2018-11-22 00:01:17 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-11-02 00:40:06 +00:00
|
|
|
contact := the.Peer.GetContact(Handle)
|
2019-10-25 19:26:25 +00:00
|
|
|
if contact != nil {
|
2019-11-02 00:40:06 +00:00
|
|
|
lastRead := initLastReadTime(contact.Onion)
|
|
|
|
unread := countUnread(contact.Timeline.GetMessages(), lastRead)
|
|
|
|
picture := initProfilePicture(Handle)
|
|
|
|
nick, exists := contact.GetAttribute(constants.Nick)
|
|
|
|
if !exists {
|
|
|
|
nick = Handle
|
2019-02-05 21:09:38 +00:00
|
|
|
}
|
|
|
|
|
2019-11-15 01:13:42 +00:00
|
|
|
this.gcd.AddContact(Handle, nick, picture, "", unread, int(connections.ConnectionStateToType[contact.State]), contact.Blocked, false, getLastMessageTime(&contact.Timeline))
|
2019-07-24 22:42:06 +00:00
|
|
|
}
|
2018-11-22 00:01:17 +00:00
|
|
|
}
|
|
|
|
|
2019-11-08 21:34:12 +00:00
|
|
|
func (this *Manager) AddSendMessageError(peer string, signature string, err string) {
|
2019-04-10 20:53:45 +00:00
|
|
|
log.Debugf("Received Error Sending Message: %v", err)
|
2019-03-05 20:16:27 +00:00
|
|
|
// FIXME: Sometimes, for the first Peer message we send our error beats our message to the UI
|
2019-04-24 20:32:20 +00:00
|
|
|
time.Sleep(time.Second * 1)
|
2019-11-08 21:34:12 +00:00
|
|
|
this.gcd.GroupSendError(signature, err)
|
2019-02-20 21:45:42 +00:00
|
|
|
}
|
|
|
|
|
2019-11-08 21:34:12 +00:00
|
|
|
func (this *Manager) AddMessage(handle string, from string, message string, fromMe bool, messageID string, timestamp time.Time, Acknowledged bool) {
|
|
|
|
nick := getOrDefault(handle, constants.Nick, handle)
|
|
|
|
image := getProfilePic(handle)
|
2018-11-22 00:01:17 +00:00
|
|
|
|
2019-07-31 22:35:35 +00:00
|
|
|
// If we have this group loaded already
|
2019-11-08 21:34:12 +00:00
|
|
|
if this.gcd.CurrentOpenConversation() == handle {
|
2019-10-22 18:55:16 +00:00
|
|
|
updateLastReadTime(handle)
|
2019-07-31 22:35:35 +00:00
|
|
|
// If the message is not from the user then add it, otherwise, just acknowledge.
|
2019-11-08 21:34:12 +00:00
|
|
|
if !fromMe {
|
|
|
|
this.gcd.AppendMessage(handle, from, nick, message, image, messageID, fromMe, timestamp.Format(constants.TIME_FORMAT), false, false)
|
2019-02-04 22:22:58 +00:00
|
|
|
} else {
|
2019-11-08 21:34:12 +00:00
|
|
|
if !Acknowledged {
|
|
|
|
this.gcd.AppendMessage(handle, from, nick, message, image, messageID, fromMe, timestamp.Format(constants.TIME_FORMAT), false, false)
|
|
|
|
} else {
|
|
|
|
this.gcd.Acknowledged(messageID)
|
|
|
|
}
|
2019-02-04 22:22:58 +00:00
|
|
|
}
|
2019-07-31 22:35:35 +00:00
|
|
|
}
|
2019-10-22 18:55:16 +00:00
|
|
|
this.gcd.IncContactUnreadCount(handle)
|
2018-11-22 00:01:17 +00:00
|
|
|
}
|
|
|
|
|
2019-11-08 21:34:12 +00:00
|
|
|
func (this *Manager) UpdateContactDisplayName(handle string, name string) {
|
|
|
|
this.gcd.UpdateContactDisplayName(handle, name)
|
2019-11-02 00:40:06 +00:00
|
|
|
}
|
2019-10-21 19:19:18 +00:00
|
|
|
|
2019-11-08 21:34:12 +00:00
|
|
|
func (this *Manager) UpdateContactStatus(handle string, status int, loading bool) {
|
|
|
|
this.gcd.UpdateContactStatus(handle, status, loading)
|
2018-11-28 20:34:49 +00:00
|
|
|
}
|
2019-02-13 07:09:39 +00:00
|
|
|
|
2019-11-08 21:34:12 +00:00
|
|
|
func (this *Manager) UpdateContactAttribute(handle, key, value string) {
|
|
|
|
this.gcd.UpdateContactAttribute(handle, key, value)
|
2019-02-13 07:09:39 +00:00
|
|
|
}
|