contact rewiring

This commit is contained in:
erinn 2021-03-12 04:24:37 -08:00
parent 77a76b6bdb
commit 659cdce84c
4 changed files with 106 additions and 84 deletions

10
lib.go
View File

@ -193,12 +193,6 @@ func GetProfiles() string {
return string(jsonBytes)
}
type Contact struct {
Name string `json:"name"`
Onion string `json:"onion"`
Status string `json:"status"`
}
//export c_GetContacts
func c_GetContacts(onion_ptr *C.char, onion_len C.int) *C.char {
return C.CString(GetContacts(C.GoStringN(onion_ptr, onion_len)))
@ -211,11 +205,11 @@ func GetContacts(onion string) string {
contactEventsQueue = event.NewQueue()
application.GetEventBus(onion).Subscribe(event.PeerStateChange, contactEventsQueue)
var contacts []Contact
var contacts []utils.Contact
for _, contact := range mypeer.GetContacts() {
contactInfo := mypeer.GetContact(contact)
log.Infof("contactInfo %v", contactInfo)
contacts = append(contacts, Contact{Name: contactInfo.Name, Onion: contactInfo.Onion, Status: contactInfo.State})
contacts = append(contacts, utils.Contact{Name: contactInfo.Name, Onion: contactInfo.Onion, Status: contactInfo.State})
}
bytes, _ := json.Marshal(contacts)

8
utils/contacts.go Normal file
View File

@ -0,0 +1,8 @@
package utils
type Contact struct {
Name string `json:"name"`
Onion string `json:"onion"`
Status string `json:"status"`
Picture string `json:"picture"`
}

View File

@ -8,12 +8,13 @@ import (
"cwtch.im/cwtch/protocol/connections"
"encoding/json"
"git.openprivacy.ca/flutter/libcwtch-go/constants"
"git.openprivacy.ca/openprivacy/log"
)
import "cwtch.im/cwtch/event"
type EventProfileEnvelope struct {
event event.Event
profile string
Event event.Event
Profile string
}
type EventHandler struct {
@ -81,39 +82,58 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
}
picPath := GetPicturePath(pic)
//tag, _ := profile.GetAttribute(app.AttributeTag)
//tag, _ := Profile.GetAttribute(app.AttributeTag)
online, _ := profile.GetAttribute(attr.GetLocalScope(constants.PeerOnline))
e.Data[constants.Name] = nick
e.Data[constants.Picture] = picPath
e.Data["Online"] = online
var contacts []Contact
for _, contact := range profile.GetContacts() {
cpicVal, ok := profile.GetContactAttribute(contact, attr.GetPeerScope(constants.Picture))
if !ok {
cpicVal = ImageToString(NewImage(RandomProfileImage(contact), TypeImageDistro))
}
cpic, err := StringToImage(cpicVal)
if err != nil {
cpic = NewImage(RandomProfileImage(contact), TypeImageDistro)
}
cpicPath := GetPicturePath(cpic)
contactInfo := profile.GetContact(contact)
contacts = append(contacts, Contact{Name: contactInfo.Name, Onion: contactInfo.Onion, Status: contactInfo.State, Picture: cpicPath,})
}
bytes, _ := json.Marshal(contacts)
e.Data["ContactsJson"] = string(bytes)
log.Infof("contactsJson %v", e.Data["ContactsJson"])
}
json, _ := json.Marshal(e)
return string(json)
}
// handleProfileEvent enriches profile events so they are usable with out further data fetches
// handleProfileEvent enriches Profile events so they are usable with out further data fetches
func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
peer := eh.app.GetPeer(ev.profile)
peer := eh.app.GetPeer(ev.Profile)
ph := NewPeerHelper(peer)
switch ev.event.EventType {
switch ev.Event.EventType {
/*case event.NetworkStatus:
/*case Event.NetworkStatus:
online, _ := peer.GetAttribute(attr.GetLocalScope(constants.PeerOnline))
if e.Data[event.Status] == plugins.NetworkCheckSuccess && online == event.False {
peer.SetAttribute(attr.GetLocalScope(constants.PeerOnline), event.True)
if e.Data[Event.Status] == plugins.NetworkCheckSuccess && online == Event.False {
peer.SetAttribute(attr.GetLocalScope(constants.PeerOnline), Event.True)
uiManager.UpdateNetworkStatus(true)
// TODO we may have to reinitialize the peer
} else if e.Data[event.Status] == plugins.NetworkCheckError && online == event.True {
peer.SetAttribute(attr.GetLocalScope(constants.PeerOnline), event.False)
} else if e.Data[Event.Status] == plugins.NetworkCheckError && online == Event.True {
peer.SetAttribute(attr.GetLocalScope(constants.PeerOnline), Event.False)
uiManager.UpdateNetworkStatus(false)
}*/
case event.NewMessageFromPeer: //event.TimestampReceived, event.RemotePeer, event.Data
case event.NewMessageFromPeer: //Event.TimestampReceived, Event.RemotePeer, Event.Data
// I Don't think we need to enrich
// TODO: deprecate and move to dart
@ -127,45 +147,45 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
}*/
// legacy
//ts, _ := time.Parse(time.RFC3339Nano, e.Data[event.TimestampReceived])
//ts, _ := time.Parse(time.RFC3339Nano, e.Data[Event.TimestampReceived])
case event.PeerAcknowledgement:
// No enrichement required
//Acknowledge(ev.event.Data[event.RemotePeer], ev.event.Data[event.EventID])
//Acknowledge(ev.Event.Data[Event.RemotePeer], ev.Event.Data[Event.EventID])
/*
case event.NewMessageFromGroup: //event.TimestampReceived, event.TimestampSent, event.Data, event.GroupID, event.RemotePeer
ts, _ := time.Parse(time.RFC3339Nano, e.Data[event.TimestampSent])
uiManager.AddMessage(e.Data[event.GroupID], e.Data[event.RemotePeer], e.Data[event.Data], e.Data[event.RemotePeer] == peer.GetOnion(), hex.EncodeToString([]byte(e.Data[event.Signature])), ts, true)
case Event.NewMessageFromGroup: //Event.TimestampReceived, Event.TimestampSent, Event.Data, Event.GroupID, Event.RemotePeer
ts, _ := time.Parse(time.RFC3339Nano, e.Data[Event.TimestampSent])
uiManager.AddMessage(e.Data[Event.GroupID], e.Data[Event.RemotePeer], e.Data[Event.Data], e.Data[Event.RemotePeer] == peer.GetOnion(), hex.EncodeToString([]byte(e.Data[Event.Signature])), ts, true)
case event.NewGroupInvite:
gid, err := peer.ProcessInvite(e.Data[event.GroupInvite], e.Data[event.RemotePeer])
case Event.NewGroupInvite:
gid, err := peer.ProcessInvite(e.Data[Event.GroupInvite], e.Data[Event.RemotePeer])
group := peer.GetGroup(gid)
if err == nil && group != nil {
uiManager.AddContact(gid)
}
*/
case event.PeerCreated:
handle := ev.event.Data[event.RemotePeer]
handle := ev.Event.Data[event.RemotePeer]
err := EnrichNewPeer(handle, ph, ev)
if err != nil {
return ""
}
/*
case event.SendMessageToGroupError:
uiManager.AddSendMessageError(e.Data[event.GroupServer], e.Data[event.Signature], e.Data[event.Error])
case event.SendMessageToPeerError:
uiManager.AddSendMessageError(e.Data[event.RemotePeer], e.Data[event.EventID], e.Data[event.Error])
case Event.SendMessageToGroupError:
uiManager.AddSendMessageError(e.Data[Event.GroupServer], e.Data[Event.Signature], e.Data[Event.Error])
case Event.SendMessageToPeerError:
uiManager.AddSendMessageError(e.Data[Event.RemotePeer], e.Data[Event.EventID], e.Data[Event.Error])
*/
case event.PeerStateChange:
cxnState := connections.ConnectionStateToType[ev.event.Data[event.ConnectionState]]
contact := peer.GetContact(ev.event.Data[event.RemotePeer])
cxnState := connections.ConnectionStateToType[ev.Event.Data[event.ConnectionState]]
contact := peer.GetContact(ev.Event.Data[event.RemotePeer])
if cxnState == connections.AUTHENTICATED && contact == nil {
// Contact does not exist, change event to NewPeer
peer.AddContact(ev.event.Data[event.RemotePeer], ev.event.Data[event.RemotePeer], model.AuthUnknown)
contact = peer.GetContact(ev.event.Data[event.RemotePeer])
ev.event.EventType = event.PeerCreated
err := EnrichNewPeer(ev.event.Data[event.RemotePeer], ph, ev)
// Contact does not exist, change Event to NewPeer
peer.AddContact(ev.Event.Data[event.RemotePeer], ev.Event.Data[event.RemotePeer], model.AuthUnknown)
contact = peer.GetContact(ev.Event.Data[event.RemotePeer])
ev.Event.EventType = event.PeerCreated
err := EnrichNewPeer(ev.Event.Data[event.RemotePeer], ph, ev)
if err != nil {
return ""
}
@ -176,17 +196,17 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
//uiManager.UpdateContactStatus(contact.Onion, int(cxnState), false)
if cxnState == connections.AUTHENTICATED {
// if known and authed, get vars
peer.SendGetValToPeer(ev.event.Data[event.RemotePeer], attr.PublicScope, constants.Name)
peer.SendGetValToPeer(ev.event.Data[event.RemotePeer], attr.PublicScope, constants.Picture)
peer.SendGetValToPeer(ev.Event.Data[event.RemotePeer], attr.PublicScope, constants.Name)
peer.SendGetValToPeer(ev.Event.Data[event.RemotePeer], attr.PublicScope, constants.Picture)
}
}
/*case event.NewRetValMessageFromPeer:
onion := e.Data[event.RemotePeer]
scope := e.Data[event.Scope]
path := e.Data[event.Path]
val := e.Data[event.Data]
exists, _ := strconv.ParseBool(e.Data[event.Exists])
/*case Event.NewRetValMessageFromPeer:
onion := e.Data[Event.RemotePeer]
scope := e.Data[Event.Scope]
path := e.Data[Event.Path]
val := e.Data[Event.Data]
exists, _ := strconv.ParseBool(e.Data[Event.Exists])
if exists && scope == attr.PublicScope {
switch path {
@ -199,14 +219,14 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
}
}
case event.ServerStateChange:
serverOnion := e.Data[event.GroupServer]
state := connections.ConnectionStateToType[e.Data[event.ConnectionState]]
case Event.ServerStateChange:
serverOnion := e.Data[Event.GroupServer]
state := connections.ConnectionStateToType[e.Data[Event.ConnectionState]]
groups := peer.GetGroups()
for _, groupID := range groups {
group := peer.GetGroup(groupID)
if group != nil && group.GroupServer == serverOnion {
group.State = e.Data[event.ConnectionState]
group.State = e.Data[Event.ConnectionState]
loading := false
if state == connections.AUTHENTICATED {
loading = true
@ -215,7 +235,7 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
uiManager.UpdateContactStatus(serverOnion, int(state), loading)
}
}
case event.DeletePeer:
case Event.DeletePeer:
log.Infof("PeerHandler got DeletePeer, SHUTTING down!\n")
uiManager.ReloadProfiles()
return
@ -250,10 +270,10 @@ func (eh *EventHandler) startHandlingPeer(onion string) {
}
func (eh *EventHandler) forwardProfileMessages(onion string, q event.Queue) {
// TODO: graceful shutdown, via an injected event of special QUIT type exiting loop/go routine
// TODO: graceful shutdown, via an injected Event of special QUIT type exiting loop/go routine
for {
e := q.Next()
ev := EventProfileEnvelope{event: *e, profile: onion}
ev := EventProfileEnvelope{Event: *e, Profile: onion}
eh.profileEvents <- ev
}
}

View File

@ -148,7 +148,7 @@ func GetPicturePath(pic *image) string {
case TypeImageDistro:
return profilePicRelativize(pic.Val)
default:
log.Errorf("Unhandled profile picture type of %v\n", pic.T)
log.Errorf("Unhandled Profile picture type of %v\n", pic.T)
return ""
}
}
@ -174,7 +174,7 @@ func getLastMessageTime(tl *model.Timeline) int {
}
/*
// AddProfile adds a new profile to the UI
// AddProfile adds a new Profile to the UI
func AddProfile(gcd *GrandCentralDispatcher, handle string) {
p := the.CwtchApp.GetPeer(handle)
if p != nil {
@ -198,20 +198,20 @@ func AddProfile(gcd *GrandCentralDispatcher, handle string) {
online, _ := p.GetAttribute(attr.GetLocalScope(constants.PeerOnline))
log.Debugf("AddProfile %v %v %v %v %v\n", handle, nick, picPath, tag, online)
gcd.AddProfile(handle, nick, picPath, tag, online == event.True)
gcd.AddProfile(handle, nick, picPath, tag, online == Event.True)
}
}*/
/*
type manager struct {
gcd *GrandCentralDispatcher
profile string
Profile string
}
// Manager is a middleware helper for entities like peer event listeners wishing to trigger ui changes (via the gcd)
// each manager is for one profile/peer
// Manager is a middleware helper for entities like peer Event listeners wishing to trigger ui changes (via the gcd)
// each manager is for one Profile/peer
// manager takes minimal arguments and builds the full struct of data (usually pulled from a cwtch peer) required to call the GCD to perform the ui action
// manager also performs call filtering based on UI state: users of manager can safely always call it on events and not have to worry about weather the relevant ui is active
// ie: you can always safely call AddMessage even if in the ui a different profile is selected. manager will check with gcd, and if the correct conditions are not met, it will not call on gcd to update the ui incorrectly
// ie: you can always safely call AddMessage even if in the ui a different Profile is selected. manager will check with gcd, and if the correct conditions are not met, it will not call on gcd to update the ui incorrectly
type Manager interface {
Acknowledge(handle, mID string)
AddContact(Handle string)
@ -234,9 +234,9 @@ type Manager interface {
UpdateNetworkStatus(online bool)
}
// NewManager returns a new Manager interface for a profile to the gcd
func NewManager(profile string, gcd *GrandCentralDispatcher) Manager {
return &manager{gcd: gcd, profile: profile}
// NewManager returns a new Manager interface for a Profile to the gcd
func NewManager(Profile string, gcd *GrandCentralDispatcher) Manager {
return &manager{gcd: gcd, Profile: Profile}
}
@ -249,28 +249,28 @@ func EnrichNewPeer(handle string, ph *PeerHelper, ev *EventProfileEnvelope) erro
group := ph.peer.GetGroup(handle)
if group != nil {
lastRead := ph.InitLastReadTime(group.GroupID)
ev.event.Data["unread"] = strconv.Itoa(ph.CountUnread(group.Timeline.GetMessages(), lastRead))
ev.event.Data["picture"] = ph.GetProfilePic(handle)
ev.Event.Data["unread"] = strconv.Itoa(ph.CountUnread(group.Timeline.GetMessages(), lastRead))
ev.Event.Data["picture"] = ph.GetProfilePic(handle)
ev.event.Data["nick"] = ph.GetNick(handle)
ev.event.Data["status"] = strconv.Itoa(int(connections.ConnectionStateToType[group.State]))
ev.event.Data["authorization"] = string(model.AuthApproved)
ev.event.Data["loading"] = "false"
ev.event.Data["lastMsgTime"] = strconv.Itoa(getLastMessageTime(&group.Timeline))
ev.Event.Data["nick"] = ph.GetNick(handle)
ev.Event.Data["status"] = strconv.Itoa(int(connections.ConnectionStateToType[group.State]))
ev.Event.Data["authorization"] = string(model.AuthApproved)
ev.Event.Data["loading"] = "false"
ev.Event.Data["lastMsgTime"] = strconv.Itoa(getLastMessageTime(&group.Timeline))
}
} else if ph.IsPeer(handle) {
contact := ph.peer.GetContact(handle)
if contact != nil {
lastRead := ph.InitLastReadTime(contact.Onion)
ev.event.Data["unread"] = strconv.Itoa(ph.CountUnread(contact.Timeline.GetMessages(), lastRead))
ev.event.Data["picture"] = ph.GetProfilePic(handle)
ev.Event.Data["unread"] = strconv.Itoa(ph.CountUnread(contact.Timeline.GetMessages(), lastRead))
ev.Event.Data["picture"] = ph.GetProfilePic(handle)
ev.event.Data["nick"] = ph.GetNick(handle)
ev.event.Data["status"] = strconv.Itoa(int(connections.ConnectionStateToType[contact.State]))
ev.Event.Data["nick"] = ph.GetNick(handle)
ev.Event.Data["status"] = strconv.Itoa(int(connections.ConnectionStateToType[contact.State]))
ev.event.Data["authorization"] = string(contact.Authorization)
ev.event.Data["loading"] = "false"
ev.event.Data["lastMsgTime"] = strconv.Itoa(getLastMessageTime(&contact.Timeline))
ev.Event.Data["authorization"] = string(contact.Authorization)
ev.Event.Data["loading"] = "false"
ev.Event.Data["lastMsgTime"] = strconv.Itoa(getLastMessageTime(&contact.Timeline))
}
} else {
// could be a server?
@ -283,7 +283,7 @@ func EnrichNewPeer(handle string, ph *PeerHelper, ev *EventProfileEnvelope) erro
/*
// AddSendMessageError adds an error not and icon to a message in a conversation in the ui for the message identified by the peer/sig combo
func (this *manager) AddSendMessageError(peer string, signature string, err string) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.DoIfProfile(this.Profile, func() {
this.gcd.DoIfConversation(peer, func() {
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
@ -304,7 +304,7 @@ func (this *manager) MessageJustAdded() {
/*
// AddMessage adds a message to the message pane for the supplied conversation if it is active
func (this *manager) AddMessage(handle string, from string, message string, fromMe bool, messageID string, timestamp time.Time, Acknowledged bool) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.DoIfProfile(this.Profile, func() {
this.gcd.DoIfConversation(handle, func() {
updateLastReadTime(handle)
// If the message is not from the user then add it, otherwise, just acknowledge.
@ -328,21 +328,21 @@ func (this *manager) ReloadProfiles() {
// UpdateContactDisplayName updates a contact's display name in the contact list and conversations
func (this *manager) UpdateContactDisplayName(handle string) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.DoIfProfile(this.Profile, func() {
this.gcd.UpdateContactDisplayName(handle, GetNick(handle))
})
}
// UpdateContactPicture updates a contact's picture in the contact list and conversations
func (this *manager) UpdateContactPicture(handle string) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.DoIfProfile(this.Profile, func() {
this.gcd.UpdateContactPicture(handle, GetProfilePic(handle))
})
}
// UpdateContactAttribute update's a contacts attribute in the ui
func (this *manager) UpdateContactAttribute(handle, key, value string) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.DoIfProfile(this.Profile, func() {
this.gcd.UpdateContactAttribute(handle, key, value)
})
}
@ -352,6 +352,6 @@ func (this *manager) ChangePasswordResponse(error bool) {
}
func (this *manager) UpdateNetworkStatus(online bool) {
this.gcd.UpdateProfileNetworkStatus(this.profile, online)
this.gcd.UpdateProfileNetworkStatus(this.Profile, online)
}
*/