remove 'badge'/unread treacking state from go code; now uses attributes to store in back end and maintain in front end
the build was successful Details

This commit is contained in:
Dan Ballard 2019-10-25 12:26:25 -07:00
parent 1ad9d5be20
commit 5bea6bdc47
9 changed files with 82 additions and 37 deletions

View File

@ -87,7 +87,7 @@ func AppEventListener(gcd *gothings.GrandCentralDispatcher, subscribed chan bool
contacts := the.Peer.GetContacts() contacts := the.Peer.GetContacts()
for i := range contacts { for i := range contacts {
contact, _ := the.Peer.GetProfile().GetContact(contacts[i]) contact, _ := the.Peer.GetProfile().GetContact(contacts[i])
displayName, _ := contact.GetAttribute("nick") displayName, _ := contact.GetAttribute(constants.Nick)
gcd.UIState.AddContact(&gobjects.Contact{ gcd.UIState.AddContact(&gobjects.Contact{
Handle: contacts[i], Handle: contacts[i],
@ -102,10 +102,11 @@ func AppEventListener(gcd *gothings.GrandCentralDispatcher, subscribed chan bool
groups := the.Peer.GetGroups() groups := the.Peer.GetGroups()
for i := range groups { for i := range groups {
group := the.Peer.GetGroup(groups[i]) group := the.Peer.GetGroup(groups[i])
nick, exists := group.GetAttribute("nick") nick, exists := group.GetAttribute(constants.Nick)
if !exists { if !exists {
nick = group.GroupID[:12] nick = group.GroupID[:12]
} }
// Only join servers for active and explicitly accepted groups. // Only join servers for active and explicitly accepted groups.
gcd.UIState.AddContact(&gobjects.Contact{ gcd.UIState.AddContact(&gobjects.Contact{
Handle: group.GroupID, Handle: group.GroupID,

View File

@ -3,6 +3,7 @@ package characters
import ( import (
"cwtch.im/cwtch/event" "cwtch.im/cwtch/event"
"cwtch.im/cwtch/protocol/connections" "cwtch.im/cwtch/protocol/connections"
"cwtch.im/ui/go/constants"
"cwtch.im/ui/go/cwutil" "cwtch.im/ui/go/cwutil"
"cwtch.im/ui/go/gobjects" "cwtch.im/ui/go/gobjects"
"cwtch.im/ui/go/gothings" "cwtch.im/ui/go/gothings"
@ -48,7 +49,7 @@ func IncomingListener(uiState *gothings.InterfaceState, subscribed chan bool) {
var exists bool var exists bool
ctc := the.Peer.GetContact(e.Data[event.RemotePeer]) ctc := the.Peer.GetContact(e.Data[event.RemotePeer])
if ctc != nil { if ctc != nil {
name, exists = ctc.GetAttribute("nick") name, exists = ctc.GetAttribute(constants.Nick)
if !exists || name == "" { if !exists || name == "" {
name = e.Data[event.RemotePeer] name = e.Data[event.RemotePeer]
} }
@ -114,7 +115,6 @@ func IncomingListener(uiState *gothings.InterfaceState, subscribed chan bool) {
e.Data[event.RemotePeer], e.Data[event.RemotePeer],
cwutil.RandomProfileImage(e.Data[event.RemotePeer]), cwutil.RandomProfileImage(e.Data[event.RemotePeer]),
"", "",
0,
int(cxnState), int(cxnState),
false, false,
false, false,

View File

@ -5,7 +5,6 @@ type Contact struct {
DisplayName string DisplayName string
Image string Image string
Server string Server string
Badge int // # of unread
Status int Status int
Trusted bool Trusted bool
Blocked bool Blocked bool

View File

@ -31,7 +31,8 @@ type GrandCentralDispatcher struct {
// contact list stuff // contact list stuff
_ func(handle, displayName, image, server string, badge, status int, trusted bool, blocked bool, loading bool) `signal:"AddContact"` _ func(handle, displayName, image, server string, badge, status int, trusted bool, blocked bool, loading bool) `signal:"AddContact"`
_ func(handle, displayName, image, server string, badge, status int, trusted bool, blocked bool, loading bool) `signal:"UpdateContact"` _ func(handle, displayName, image, server string, status int, trusted bool, blocked bool, loading bool) `signal:"UpdateContact"`
_ func(handle string) `signal:"IncContactUnreadCount"`
_ func(handle string) `signal:"RemoveContact"` _ func(handle string) `signal:"RemoveContact"`
_ func(handle, key, value string) `signal:"UpdateContactAttribute"` _ func(handle, key, value string) `signal:"UpdateContactAttribute"`
@ -171,20 +172,18 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) {
cwutil.RandomProfileImage(handle), cwutil.RandomProfileImage(handle),
"", "",
0, 0,
0,
false, false,
false, false,
false, false,
}) })
} else { } else {
c.Badge = 0
this.UIState.UpdateContact(handle) this.UIState.UpdateContact(handle)
} }
if len(handle) == 32 { // LOAD GROUP if len(handle) == 32 { // LOAD GROUP
group := the.Peer.GetGroup(handle) group := the.Peer.GetGroup(handle)
tl := group.GetTimeline() tl := group.GetTimeline()
nick, _ := group.GetAttribute("nick") nick, _ := group.GetAttribute(constants.Nick)
if nick == "" { if nick == "" {
this.SetToolbarTitle(handle) this.SetToolbarTitle(handle)
} else { } else {
@ -201,7 +200,7 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) {
var exists bool var exists bool
ctc := the.Peer.GetContact(tl[i].PeerID) ctc := the.Peer.GetContact(tl[i].PeerID)
if ctc != nil { if ctc != nil {
name, exists = ctc.GetAttribute("nick") name, exists = ctc.GetAttribute(constants.Nick)
if !exists || name == "" { if !exists || name == "" {
name = tl[i].PeerID name = tl[i].PeerID
} }
@ -228,7 +227,7 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) {
contact, _ := the.Peer.GetProfile().GetContact(handle) contact, _ := the.Peer.GetProfile().GetContact(handle)
var nick string var nick string
if contact != nil { if contact != nil {
nick, _ = contact.GetAttribute("nick") nick, _ = contact.GetAttribute(constants.Nick)
if nick == "" { if nick == "" {
nick = handle nick = handle
} }
@ -248,7 +247,7 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) {
ctc := the.Peer.GetContact(messages[i].PeerID) ctc := the.Peer.GetContact(messages[i].PeerID)
if ctc != nil { if ctc != nil {
var exists bool var exists bool
displayname, exists = ctc.GetAttribute("nick") displayname, exists = ctc.GetAttribute(constants.Nick)
if !exists || displayname == "" { if !exists || displayname == "" {
displayname = messages[i].PeerID displayname = messages[i].PeerID
} }
@ -300,7 +299,7 @@ func (this *GrandCentralDispatcher) requestPeerSettings() {
return return
} }
name, exists := contact.GetAttribute("nick") name, exists := contact.GetAttribute(constants.Nick)
if !exists { if !exists {
log.Errorf("error: couldn't find contact %v", this.CurrentOpenConversation()) log.Errorf("error: couldn't find contact %v", this.CurrentOpenConversation())
this.SupplyPeerSettings(this.CurrentOpenConversation(), this.CurrentOpenConversation(), contact.Blocked) this.SupplyPeerSettings(this.CurrentOpenConversation(), this.CurrentOpenConversation(), contact.Blocked)
@ -317,10 +316,10 @@ func (this *GrandCentralDispatcher) savePeerSettings(onion, nick string) {
return return
} }
contact.SetAttribute("nick", nick) contact.SetAttribute(constants.Nick, nick)
the.EventBus.Publish(event.NewEvent(event.SetPeerAttribute, map[event.Field]string{ the.EventBus.Publish(event.NewEvent(event.SetPeerAttribute, map[event.Field]string{
event.RemotePeer: onion, event.RemotePeer: onion,
event.Key: "nick", event.Key: constants.Nick,
event.Data: nick, event.Data: nick,
})) }))
@ -338,13 +337,13 @@ func (this *GrandCentralDispatcher) requestGroupSettings(groupID string) {
return return
} }
nick, _ := group.GetAttribute("nick") nick, _ := group.GetAttribute(constants.Nick)
invite, _ := the.Peer.ExportGroup(groupID) invite, _ := the.Peer.ExportGroup(groupID)
contactaddrs := the.Peer.GetContacts() contactaddrs := the.Peer.GetContacts()
contactnames := make([]string, len(contactaddrs)) contactnames := make([]string, len(contactaddrs))
for i, contact := range contactaddrs { for i, contact := range contactaddrs {
name, hasname := the.Peer.GetContact(contact).GetAttribute("nick") name, hasname := the.Peer.GetContact(contact).GetAttribute(constants.Nick)
if hasname { if hasname {
contactnames[i] = name contactnames[i] = name
} else { } else {
@ -363,10 +362,10 @@ func (this *GrandCentralDispatcher) saveGroupSettings(groupID, nick string) {
return return
} }
group.SetAttribute("nick", nick) group.SetAttribute(constants.Nick, nick)
the.EventBus.Publish(event.NewEvent(event.SetGroupAttribute, map[event.Field]string{ the.EventBus.Publish(event.NewEvent(event.SetGroupAttribute, map[event.Field]string{
event.GroupID: groupID, event.GroupID: groupID,
event.Key: "nick", event.Key: constants.Nick,
event.Data: nick, event.Data: nick,
})) }))
@ -480,10 +479,10 @@ func (this *GrandCentralDispatcher) createGroup(server, groupName string) {
}) })
group := the.Peer.GetGroup(groupID) group := the.Peer.GetGroup(groupID)
group.SetAttribute("nick", groupName) group.SetAttribute(constants.Nick, groupName)
the.EventBus.Publish(event.NewEvent(event.SetGroupAttribute, map[event.Field]string{ the.EventBus.Publish(event.NewEvent(event.SetGroupAttribute, map[event.Field]string{
event.GroupID: groupID, event.GroupID: groupID,
event.Key: "nick", event.Key: constants.Nick,
event.Data: groupName, event.Data: groupName,
})) }))

View File

@ -1,6 +1,7 @@
package gothings package gothings
import ( import (
"cwtch.im/cwtch/model"
"cwtch.im/ui/go/constants" "cwtch.im/ui/go/constants"
"cwtch.im/ui/go/cwutil" "cwtch.im/ui/go/cwutil"
"cwtch.im/ui/go/gobjects" "cwtch.im/ui/go/gobjects"
@ -11,6 +12,39 @@ import (
"time" "time"
) )
type Attributable interface {
GetAttribute(string) (string, bool)
SetAttribute(string, string)
}
// initLastReadTime checks and gets the Attributable's LastRead time or sets it to now
func initLastReadTime(attr Attributable) time.Time {
lastRead := time.Now()
lastReadVal, ok := attr.GetAttribute(constants.LastRead)
if ok {
err := lastRead.UnmarshalText([]byte(lastReadVal))
if err != nil {
lastRead = time.Now()
}
} else {
lastReadVal, _ := lastRead.MarshalText()
attr.SetAttribute(constants.LastRead, string(lastReadVal))
}
return lastRead
}
func countUnread(messages []model.Message, lastRead time.Time) int {
count := 0
for i := len(messages) - 1; i >= 0; i-- {
if messages[i].Timestamp.After(lastRead) {
count++
} else {
break
}
}
return count
}
type InterfaceState struct { type InterfaceState struct {
parentGcd *GrandCentralDispatcher parentGcd *GrandCentralDispatcher
contacts sync.Map // string : *gobjects.Contact contacts sync.Map // string : *gobjects.Contact
@ -27,8 +61,14 @@ func (this *InterfaceState) Acknowledge(mID string) {
func (this *InterfaceState) AddContact(c *gobjects.Contact) { func (this *InterfaceState) AddContact(c *gobjects.Contact) {
if len(c.Handle) == 32 { // ADD GROUP if len(c.Handle) == 32 { // ADD GROUP
unread := 0
group := the.Peer.GetGroup(c.Handle)
if group != nil {
lastRead := initLastReadTime(group)
unread = countUnread(group.Timeline.GetMessages(), lastRead)
}
if _, found := this.contacts.Load(c.Handle); !found { 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.Blocked, c.Loading) this.parentGcd.AddContact(c.Handle, c.DisplayName, c.Image, c.Server, unread, c.Status, c.Trusted, c.Blocked, c.Loading)
this.contacts.Store(c.Handle, c) this.contacts.Store(c.Handle, c)
} }
return return
@ -38,9 +78,15 @@ func (this *InterfaceState) AddContact(c *gobjects.Contact) {
return return
} }
unread := 0
contact := the.Peer.GetContact(c.Handle)
if contact != nil {
lastRead := initLastReadTime(contact)
unread = countUnread(contact.Timeline.GetMessages(), lastRead)
}
if _, found := this.contacts.Load(c.Handle); !found { if _, found := this.contacts.Load(c.Handle); !found {
this.contacts.Store(c.Handle, c) this.contacts.Store(c.Handle, c)
this.parentGcd.AddContact(c.Handle, c.DisplayName, c.Image, c.Server, c.Badge, c.Status, c.Trusted, c.Blocked, false) this.parentGcd.AddContact(c.Handle, c.DisplayName, c.Image, c.Server, unread, c.Status, c.Trusted, c.Blocked, false)
if the.Peer.GetContact(c.Handle) == nil { if the.Peer.GetContact(c.Handle) == nil {
the.Peer.AddContact(c.DisplayName, c.Handle, c.Trusted) the.Peer.AddContact(c.DisplayName, c.Handle, c.Trusted)
go the.Peer.PeerWithOnion(c.Handle) go the.Peer.PeerWithOnion(c.Handle)
@ -57,7 +103,7 @@ func (this *InterfaceState) GetContact(handle string) *gobjects.Contact {
if len(handle) == 32 { if len(handle) == 32 {
group := the.Peer.GetGroup(handle) group := the.Peer.GetGroup(handle)
if group != nil { if group != nil {
nick, exists := group.GetAttribute("nick") nick, exists := group.GetAttribute(constants.Nick)
if !exists { if !exists {
nick = group.GroupID[:12] nick = group.GroupID[:12]
} }
@ -67,7 +113,6 @@ func (this *InterfaceState) GetContact(handle string) *gobjects.Contact {
cwutil.RandomGroupImage(handle), cwutil.RandomGroupImage(handle),
group.GroupServer, group.GroupServer,
0, 0,
0,
group.Accepted, group.Accepted,
false, false,
false, false,
@ -88,7 +133,6 @@ func (this *InterfaceState) GetContact(handle string) *gobjects.Contact {
cwutil.RandomProfileImage(handle), cwutil.RandomProfileImage(handle),
"", "",
0, 0,
0,
false, false,
contact.Blocked, contact.Blocked,
false, false,
@ -126,11 +170,7 @@ func (this *InterfaceState) AddMessage(m *gobjects.Message) {
this.parentGcd.Acknowledged(m.MessageID) this.parentGcd.Acknowledged(m.MessageID)
} }
} else { } else {
c := this.GetContact(m.Handle) this.parentGcd.IncContactUnreadCount(m.Handle)
if c != nil {
c.Badge++
this.UpdateContact(c.Handle)
}
} }
} }
@ -142,7 +182,7 @@ func (this *InterfaceState) UpdateContact(handle string) {
if contact != nil { if contact != nil {
c.Blocked = contact.Blocked c.Blocked = contact.Blocked
} }
this.parentGcd.UpdateContact(c.Handle, c.DisplayName, c.Image, c.Server, c.Badge, c.Status, c.Trusted, c.Blocked, c.Loading) this.parentGcd.UpdateContact(c.Handle, c.DisplayName, c.Image, c.Server, c.Status, c.Trusted, c.Blocked, c.Loading)
} }
} }

View File

@ -92,7 +92,7 @@ ColumnLayout {
} }
} }
onUpdateContact: function(_handle, _displayName, _image, _server, _badge, _status, _trusted, _blocked, _loading) { onUpdateContact: function(_handle, _displayName, _image, _server, _status, _trusted, _blocked, _loading) {
if (gcd.currentOpenConversation == _handle) { if (gcd.currentOpenConversation == _handle) {
if (_loading == true) { if (_loading == true) {
newposttitle.enabled = false newposttitle.enabled = false

View File

@ -110,7 +110,7 @@ ColumnLayout {
messagesListView.positionViewAtEnd() messagesListView.positionViewAtEnd()
} }
onUpdateContact: function(_handle, _displayName, _image, _server, _badge, _status, _trusted, _blocked, _loading) { onUpdateContact: function(_handle, _displayName, _image, _server, _status, _trusted, _blocked, _loading) {
if (gcd.currentOpenConversation == _handle) { if (gcd.currentOpenConversation == _handle) {
// Group is Synced OR p2p is Authenticated // Group is Synced OR p2p is Authenticated
if ( (_handle.length == 32 && _status == 4) || _status == 3) { if ( (_handle.length == 32 && _status == 4) || _status == 3) {

View File

@ -96,7 +96,7 @@ ColumnLayout {
} }
} }
onUpdateContact: function(_handle, _displayName, _image, _server, _badge, _status, _trusted, _blocked, _loading) { onUpdateContact: function(_handle, _displayName, _image, _server, _status, _trusted, _blocked, _loading) {
if (gcd.currentOpenConversation == _handle) { if (gcd.currentOpenConversation == _handle) {
if (_loading == true) { if (_loading == true) {
newposttitle.enabled = false newposttitle.enabled = false

View File

@ -123,6 +123,7 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY
isActive = true isActive = true
theStack.pane = theStack.messagePane theStack.pane = theStack.messagePane
gcd.loadMessagesPane(handle) gcd.loadMessagesPane(handle)
badge = 0
if (handle.length == 32) { if (handle.length == 32) {
gcd.requestGroupSettings(handle) gcd.requestGroupSettings(handle)
} }
@ -145,17 +146,22 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY
isActive = false isActive = false
} }
onUpdateContact: function(_handle, _displayName, _image, _server, _badge, _status, _trusted, _blocked, _loading) { onUpdateContact: function(_handle, _displayName, _image, _server, _status, _trusted, _blocked, _loading) {
if (handle == _handle) { if (handle == _handle) {
displayName = _displayName + (_blocked == true ? " (blocked)" : "") displayName = _displayName + (_blocked == true ? " (blocked)" : "")
image = _image image = _image
server = _server server = _server
badge = _badge
status = _status status = _status
trusted = _trusted trusted = _trusted
blocked = _blocked blocked = _blocked
loadingProgress.visible = loadingProgress.running = loading = _loading loadingProgress.visible = loadingProgress.running = loading = _loading
} }
} }
onIncContactUnreadCount: function(handle) {
if (handle == _handle) {
badge++
}
}
} }
} }