diff --git a/go.mod b/go.mod index c412f01e..a3e05401 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module cwtch.im/ui go 1.12 require ( - cwtch.im/cwtch v0.3.2 + cwtch.im/cwtch v0.3.3 git.openprivacy.ca/openprivacy/libricochet-go v1.0.6 github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect github.com/kr/pretty v0.1.0 // indirect diff --git a/go.sum b/go.sum index c576e4e6..ead507ab 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ cwtch.im/cwtch v0.3.1 h1:C0DLIrOqpNs5aecKTjNJZhpMq4/EvWNmLiKklIS8RTM= cwtch.im/cwtch v0.3.1/go.mod h1:8tmtp3c7fccWw9H7s9u6E8GD2PKI3ar21i0fjN8pzd0= cwtch.im/cwtch v0.3.2 h1:JxoauToMckHjmQz3QCmI7XG9pun1tF3pV/o5ziuqV1A= cwtch.im/cwtch v0.3.2/go.mod h1:4b2qGW5bZKm4CwYxqc0+4pgpDU0LjjyoihC8a/ezOoQ= +cwtch.im/cwtch v0.3.3 h1:mAypnkTCehej5ebSEzl43nPufsyyXLNz/dw2RWOO+Wk= +cwtch.im/cwtch v0.3.3/go.mod h1:I95rbE3aK8uic7LsMOB1lfJDSzlNsRUP0/5cFCLkD0Y= cwtch.im/tapir v0.1.10 h1:V+TkmwXNd6gySZqlVw468wMYEkmDwMSyvhkkpOfUw7w= cwtch.im/tapir v0.1.10/go.mod h1:EuRYdVrwijeaGBQ4OijDDRHf7R2MDSypqHkSl5DxI34= cwtch.im/tapir v0.1.11 h1:JLm1MIYq4VXKzhj68+P8OuVPllAU9U6G0DtUor2fbc4= @@ -14,6 +16,7 @@ git.openprivacy.ca/openprivacy/libricochet-go v1.0.6/go.mod h1:yMSG1gBaP4f1U+RMZ github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= github.com/c-bata/go-prompt v0.2.3/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cretz/bine v0.1.0 h1:1/fvhLE+fk0bPzjdO5Ci+0ComYxEMuB1JhM4X5skT3g= github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -25,6 +28,7 @@ github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f h1:KMlcu9X58lhTA/KrfX8Bi1LQSO4pzoVjTiL3h4Jk+Zk= github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gordonklaus/ineffassign v0.0.0-20190601041439-ed7b1b5ee0f8/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= @@ -61,14 +65,17 @@ golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190420063019-afa5a82059c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -78,7 +85,10 @@ golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191031220737-6d8f1af9ccc0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/go/characters/appEventListener.go b/go/characters/appEventListener.go index 2ea4fec7..b87abe17 100644 --- a/go/characters/appEventListener.go +++ b/go/characters/appEventListener.go @@ -5,7 +5,6 @@ import ( "cwtch.im/cwtch/event" "cwtch.im/ui/go/constants" "cwtch.im/ui/go/cwutil" - "cwtch.im/ui/go/gobjects" "cwtch.im/ui/go/gothings" "cwtch.im/ui/go/the" "git.openprivacy.ca/openprivacy/libricochet-go/log" @@ -86,36 +85,13 @@ func AppEventListener(gcd *gothings.GrandCentralDispatcher, subscribed chan bool contacts := the.Peer.GetContacts() for i := range contacts { - contact, _ := the.Peer.GetProfile().GetContact(contacts[i]) - displayName, _ := contact.GetAttribute(constants.Nick) - - gcd.UIState.AddContact(&gobjects.Contact{ - Handle: contacts[i], - DisplayName: displayName, - Image: cwutil.RandomProfileImage(contacts[i]), - Trusted: contact.Trusted, - Blocked: contact.Blocked, - Loading: false, - }) + gcd.UIState.AddContact(contacts[i]) } groups := the.Peer.GetGroups() for i := range groups { - group := the.Peer.GetGroup(groups[i]) - nick, exists := group.GetAttribute(constants.Nick) - if !exists { - nick = group.GroupID[:12] - } - // Only join servers for active and explicitly accepted groups. - gcd.UIState.AddContact(&gobjects.Contact{ - Handle: group.GroupID, - DisplayName: nick, - Image: cwutil.RandomGroupImage(group.GroupID), - Server: group.GroupServer, - Trusted: group.Accepted, - Loading: false, - }) + gcd.UIState.AddContact(groups[i]) } if e.Data[event.Status] != "running" { diff --git a/go/characters/incominglistener.go b/go/characters/incominglistener.go index 0a639075..b45a97be 100644 --- a/go/characters/incominglistener.go +++ b/go/characters/incominglistener.go @@ -73,14 +73,7 @@ func IncomingListener(uiState *gothings.InterfaceState, subscribed chan bool) { gid, err := the.Peer.GetProfile().ProcessInvite(e.Data[event.GroupInvite], e.Data[event.RemotePeer]) group := the.Peer.GetGroup(gid) if err == nil && group != nil { - uiState.AddContact(&gobjects.Contact{ - Handle: gid, - DisplayName: gid, - Image: cwutil.RandomGroupImage(gid), - Server: group.GroupServer, - Trusted: false, - Loading: false, - }) + uiState.AddContact(gid) } case event.SendMessageToGroupError: uiState.AddSendMessageError(e.Data[event.GroupServer], e.Data[event.Signature], e.Data[event.Error]) @@ -90,37 +83,21 @@ func IncomingListener(uiState *gothings.InterfaceState, subscribed chan bool) { cxnState := connections.ConnectionStateToType[e.Data[event.ConnectionState]] // if it's not in the.Peer it's new. Only add once Authed - _, exists := the.Peer.GetProfile().Contacts[e.Data[event.RemotePeer]] - if !exists { + if _, exists := the.Peer.GetProfile().Contacts[e.Data[event.RemotePeer]]; !exists { // Contact does not exist, we will add them but we won't know who they are until they are authenticated // So if we get any other state from an unknown contact we do nothing // (the next exists check will fail) if cxnState == connections.AUTHENTICATED { the.Peer.AddContact(e.Data[event.RemotePeer], e.Data[event.RemotePeer], false) + uiState.AddContact(e.Data[event.RemotePeer]) } } // if it's in the.Peer its either existing and needs an update or not in the UI and needs to be added if contact, exists := the.Peer.GetProfile().Contacts[e.Data[event.RemotePeer]]; exists { contact.State = e.Data[event.ConnectionState] - uiContact := uiState.GetContact(contact.Onion) - if uiContact != nil { - if uiContact.Status != int(cxnState) { - uiContact.Status = int(cxnState) - uiState.UpdateContact(contact.Onion) - } - } else { - uiState.AddContact(&gobjects.Contact{ - e.Data[event.RemotePeer], - e.Data[event.RemotePeer], - cwutil.RandomProfileImage(e.Data[event.RemotePeer]), - "", - int(cxnState), - false, - false, - false, - }) - } + uiState.UpdateContactStatus(contact.Onion, int(cxnState), false) + } case event.ServerStateChange: serverOnion := e.Data[event.GroupServer] @@ -128,15 +105,13 @@ func IncomingListener(uiState *gothings.InterfaceState, subscribed chan bool) { groups := the.Peer.GetGroups() for _, groupID := range groups { group := the.Peer.GetGroup(groupID) - group.State = e.Data[event.ConnectionState] if group != nil && group.GroupServer == serverOnion { - uiState.GetContact(group.GroupID).Status = int(state) + group.State = e.Data[event.ConnectionState] + loading := false if state == connections.AUTHENTICATED { - uiState.GetContact(group.GroupID).Loading = true - } else { - uiState.GetContact(group.GroupID).Loading = false + loading = true } - uiState.UpdateContact(group.GroupID) + uiState.UpdateContactStatus(group.GroupID, int(state), loading) } else { log.Errorf("found group that is nil :/") } diff --git a/go/constants/attributes.go b/go/constants/attributes.go index a95dc873..10065d64 100644 --- a/go/constants/attributes.go +++ b/go/constants/attributes.go @@ -2,3 +2,4 @@ package constants const Nick = "nick" const LastRead = "last-read" +const Picture = "picture" diff --git a/go/cwutil/utils.go b/go/cwutil/utils.go index 53bcf1d2..e3f6490a 100644 --- a/go/cwutil/utils.go +++ b/go/cwutil/utils.go @@ -3,7 +3,6 @@ package cwutil import ( "encoding/base32" "encoding/hex" - "fmt" "git.openprivacy.ca/openprivacy/libricochet-go/log" "strings" ) @@ -23,7 +22,7 @@ func RandomGroupImage(handle string) string { choices := []string{"001-borobudur", "002-opera-house", "003-burj-al-arab", "004-chrysler", "005-acropolis", "006-empire-state-building", "007-temple", "008-indonesia-1", "009-new-zealand", "010-notre-dame", "011-space-needle", "012-seoul", "013-mosque", "014-milan", "015-statue", "016-pyramid", "017-cologne", "018-brandenburg-gate", "019-berlin-cathedral", "020-hungarian-parliament", "021-buckingham", "022-thailand", "023-independence", "024-angkor-wat", "025-vaticano", "026-christ-the-redeemer", "027-colosseum", "028-golden-gate-bridge", "029-sphinx", "030-statue-of-liberty", "031-cradle-of-humankind", "032-istanbul", "033-london-eye", "034-sagrada-familia", "035-tower-bridge", "036-burj-khalifa", "037-washington", "038-big-ben", "039-stonehenge", "040-white-house", "041-ahu-tongariki", "042-capitol", "043-eiffel-tower", "044-church-of-the-savior-on-spilled-blood", "045-arc-de-triomphe", "046-windmill", "047-louvre", "048-torii-gate", "049-petronas", "050-matsumoto-castle", "051-fuji", "052-temple-of-heaven", "053-pagoda", "054-chichen-itza", "055-forbidden-city", "056-merlion", "057-great-wall-of-china", "058-taj-mahal", "059-pisa", "060-indonesia"} barr, err := hex.DecodeString(handle) if err != nil || len(barr) == 0 { - fmt.Printf("error: %v %v %v\n", handle, err, barr) + log.Errorf("error: %v %v %v\n", handle, err, barr) return "qrc:/qml/images/extra/openprivacy.png" } return "qrc:/qml/images/servers/" + choices[int(barr[0])%len(choices)] + ".png" diff --git a/go/gobjects/contact.go b/go/gobjects/contact.go deleted file mode 100644 index 75807d56..00000000 --- a/go/gobjects/contact.go +++ /dev/null @@ -1,12 +0,0 @@ -package gobjects - -type Contact struct { - Handle string - DisplayName string - Image string - Server string - Status int - Trusted bool - Blocked bool - Loading bool -} diff --git a/go/gothings/gcd.go b/go/gothings/gcd.go index 0caf4499..46169e35 100644 --- a/go/gothings/gcd.go +++ b/go/gothings/gcd.go @@ -2,6 +2,7 @@ package gothings import ( "cwtch.im/cwtch/event" + "cwtch.im/cwtch/protocol/connections" "cwtch.im/ui/go/constants" "cwtch.im/ui/go/cwutil" "github.com/therecipe/qt/qml" @@ -30,11 +31,13 @@ type GrandCentralDispatcher struct { _ string `property:"buildDate"` // 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, status int, trusted bool, blocked bool, loading bool) `signal:"UpdateContact"` - _ func(handle string) `signal:"IncContactUnreadCount"` - _ func(handle string) `signal:"RemoveContact"` - _ func(handle, key, value string) `signal:"UpdateContactAttribute"` + _ func(handle, displayName, image, server string, badge, status int, blocked bool, loading bool) `signal:"AddContact"` + _ func(handle, displayName string) `signal:"UpdateContactDisplayName"` + _ func(handle string, status int, loading bool) `signal:"UpdateContactStatus"` + _ func(handle string, blocked bool) `signal:"UpdateContactBlocked"` + _ func(handle string) `signal:"IncContactUnreadCount"` + _ func(handle string) `signal:"RemoveContact"` + _ func(handle, key, value string) `signal:"UpdateContactAttribute"` // messages pane stuff _ func(handle, from, displayName, message, image string, mID string, fromMe bool, ts string, ackd bool, error bool) `signal:"AppendMessage"` @@ -94,16 +97,13 @@ func (this *GrandCentralDispatcher) sendMessage(message string, mID string) { return } - if len(this.CurrentOpenConversation()) == 32 { // SEND TO GROUP + if isGroup(this.CurrentOpenConversation()) { if !the.Peer.GetGroup(this.CurrentOpenConversation()).Accepted { err := the.Peer.AcceptInvite(this.CurrentOpenConversation()) if err != nil { log.Errorf("tried to mark a nonexistent group as existed. bad!") return } - c := this.UIState.GetContact(this.CurrentOpenConversation()) - c.Trusted = true - this.UIState.UpdateContact(c.Handle) } var err error @@ -127,13 +127,6 @@ func (this *GrandCentralDispatcher) sendMessage(message string, mID string) { return } } else { - - // TODO: require explicit invite accept/reject instead of implicitly trusting on send - if !this.UIState.GetContact(this.CurrentOpenConversation()).Trusted { - this.UIState.GetContact(this.CurrentOpenConversation()).Trusted = true - this.UIState.UpdateContact(this.CurrentOpenConversation()) - } - to := this.CurrentOpenConversation() mID = the.Peer.SendMessageToPeer(to, message) @@ -163,28 +156,20 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) { } this.ClearMessages() this.SetCurrentOpenConversation(handle) - c := this.UIState.GetContact(handle) - if c == nil { - this.UIState.AddContact(&gobjects.Contact{ - handle, - handle, - cwutil.RandomProfileImage(handle), - "", - 0, - false, - false, - false, - }) - } else { - this.UIState.UpdateContact(handle) - } - - if len(handle) == 32 { // LOAD GROUP + if isGroup(handle) { // LOAD GROUP group := the.Peer.GetGroup(handle) + + loading := false + state := connections.ConnectionStateToType[group.State] + if state == connections.AUTHENTICATED { + loading = true + } + this.UpdateContactStatus(group.GroupID, int(state), loading) + tl := group.GetTimeline() nick, _ := group.GetAttribute(constants.Nick) - updateLastReadTime(group) + updateLastReadTime(group.GroupID) if nick == "" { this.SetToolbarTitle(handle) } else { @@ -226,6 +211,9 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) { } // ELSE LOAD CONTACT contact, _ := the.Peer.GetProfile().GetContact(handle) + + this.UpdateContactStatus(handle, int(connections.ConnectionStateToType[contact.State]), false) + var nick string if contact != nil { nick, _ = contact.GetAttribute(constants.Nick) @@ -233,7 +221,7 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) { nick = handle } } - updateLastReadTime(contact) + updateLastReadTime(contact.Onion) this.SetToolbarTitle(nick) peer := the.Peer.GetContact(handle) @@ -286,11 +274,7 @@ func (this *GrandCentralDispatcher) saveSettings(zoom, locale string) { return } - the.EventBus.Publish(event.NewEvent(event.SetAttribute, map[event.Field]string{ - event.Key: constants.ZoomSetting, - event.Data: zoom, - })) - the.Peer.GetProfile().SetAttribute(constants.ZoomSetting, zoom) + the.Peer.SetAttribute(constants.ZoomSetting, zoom) } func (this *GrandCentralDispatcher) requestPeerSettings() { @@ -312,23 +296,8 @@ func (this *GrandCentralDispatcher) requestPeerSettings() { } func (this *GrandCentralDispatcher) savePeerSettings(onion, nick string) { - contact := the.Peer.GetContact(onion) - if contact == nil { - log.Errorf("error: tried to save settings for unknown peer %v", onion) - return - } - - contact.SetAttribute(constants.Nick, nick) - the.EventBus.Publish(event.NewEvent(event.SetPeerAttribute, map[event.Field]string{ - event.RemotePeer: onion, - event.Key: constants.Nick, - event.Data: nick, - })) - - cif, _ := this.UIState.contacts.Load(onion) - c := cif.(*gobjects.Contact) - c.DisplayName = nick - this.UIState.UpdateContact(onion) + the.Peer.SetContactAttribute(onion, constants.Nick, nick) + this.UpdateContactDisplayName(onion, nick) } func (this *GrandCentralDispatcher) requestGroupSettings(groupID string) { @@ -357,24 +326,8 @@ func (this *GrandCentralDispatcher) requestGroupSettings(groupID string) { } func (this *GrandCentralDispatcher) saveGroupSettings(groupID, nick string) { - group := the.Peer.GetGroup(groupID) - - if group == nil { - log.Errorf("couldn't find group %v", groupID) - return - } - - group.SetAttribute(constants.Nick, nick) - the.EventBus.Publish(event.NewEvent(event.SetGroupAttribute, map[event.Field]string{ - event.GroupID: groupID, - event.Key: constants.Nick, - event.Data: nick, - })) - - cif, _ := this.UIState.contacts.Load(groupID) - c := cif.(*gobjects.Contact) - c.DisplayName = nick - this.UIState.UpdateContact(groupID) + the.Peer.SetGroupAttribute(groupID, constants.Nick, nick) + this.UpdateContactDisplayName(groupID, nick) } func (this *GrandCentralDispatcher) broadcast(signal string) { @@ -446,12 +399,7 @@ func (this *GrandCentralDispatcher) importString(str string) { return //TODO: bring them to the duplicate } - this.UIState.AddContact(&gobjects.Contact{ - Handle: onion, - DisplayName: name, - Image: cwutil.RandomProfileImage(onion), - Trusted: true, - }) + this.UIState.AddContact(onion) } func (this *GrandCentralDispatcher) popup(str string) { @@ -472,21 +420,9 @@ func (this *GrandCentralDispatcher) createGroup(server, groupName string) { return } - this.UIState.AddContact(&gobjects.Contact{ - Handle: groupID, - DisplayName: groupName, - Image: cwutil.RandomGroupImage(groupID), - Server: server, - Trusted: true, - }) + this.UIState.AddContact(groupID) - group := the.Peer.GetGroup(groupID) - group.SetAttribute(constants.Nick, groupName) - the.EventBus.Publish(event.NewEvent(event.SetGroupAttribute, map[event.Field]string{ - event.GroupID: groupID, - event.Key: constants.Nick, - event.Data: groupName, - })) + the.Peer.SetGroupAttribute(groupID, constants.Nick, groupName) the.Peer.JoinServer(server) } @@ -496,7 +432,7 @@ func (this *GrandCentralDispatcher) blockPeer(onion string) { if err != nil { this.InvokePopup("Error Blocking Peer: " + err.Error()) } - this.UIState.UpdateContact(onion) + this.UpdateContactBlocked(onion, true) } func (this *GrandCentralDispatcher) unblockPeer(onion string) { @@ -505,7 +441,7 @@ func (this *GrandCentralDispatcher) unblockPeer(onion string) { this.InvokePopup("Error Unblocking Peer: " + err.Error()) } the.Peer.PeerWithOnion(onion) - this.UIState.UpdateContact(onion) + this.UpdateContactBlocked(onion, false) } func (this *GrandCentralDispatcher) inviteToGroup(onion, groupID string) { @@ -528,54 +464,28 @@ func (this *GrandCentralDispatcher) deleteContact(onion string) { func (this *GrandCentralDispatcher) acceptGroup(groupID string) { if the.Peer.GetGroup(groupID) != nil { the.Peer.AcceptInvite(groupID) - this.UIState.UpdateContact(groupID) } } func (this *GrandCentralDispatcher) setAttribute(onion, key, value string) { - pp, _ := the.Peer.GetProfile().GetContact(onion) - if pp != nil { - pp.SetAttribute(key, value) - the.EventBus.Publish(event.NewEvent(event.SetPeerAttribute, map[event.Field]string{ - event.RemotePeer: onion, - event.Key: key, - event.Data: value, - })) - this.UIState.UpdateContactAttribute(onion, key, value) - } + the.Peer.SetContactAttribute(onion, key, value) + this.UIState.UpdateContactAttribute(onion, key, value) } func (this *GrandCentralDispatcher) blockUnknownPeers() { - - // Save this setting - the.EventBus.Publish(event.NewEvent(event.SetAttribute, map[event.Field]string{ - event.Key: constants.BlockUnknownPeersSetting, - event.Data: "true", - })) - - the.Peer.GetProfile().SetAttribute(constants.BlockUnknownPeersSetting, "true") + the.Peer.SetAttribute(constants.BlockUnknownPeersSetting, "true") the.EventBus.Publish(event.NewEvent(event.BlockUnknownPeers, map[event.Field]string{})) } func (this *GrandCentralDispatcher) allowUnknownPeers() { - - // Save this setting - the.EventBus.Publish(event.NewEvent(event.SetAttribute, map[event.Field]string{ - event.Key: constants.BlockUnknownPeersSetting, - event.Data: "false", - })) - - the.Peer.GetProfile().SetAttribute(constants.BlockUnknownPeersSetting, "false") + the.Peer.SetAttribute(constants.BlockUnknownPeersSetting, "false") the.EventBus.Publish(event.NewEvent(event.AllowUnknownPeers, map[event.Field]string{})) } func (this *GrandCentralDispatcher) setLocale(locale string) { this.SetLocale_helper(locale) - the.EventBus.Publish(event.NewEvent(event.SetAttribute, map[event.Field]string{ - event.Key: constants.LocaleSetting, - event.Data: locale, - })) + the.Peer.SetAttribute(constants.LocaleSetting, locale) zoom, _ := the.Peer.GetProfile().GetAttribute(constants.ZoomSetting) blockunkownpeers, _ := the.Peer.GetProfile().GetAttribute(constants.BlockUnknownPeersSetting) diff --git a/go/gothings/uistate.go b/go/gothings/uistate.go index 14dae73d..745b1952 100644 --- a/go/gothings/uistate.go +++ b/go/gothings/uistate.go @@ -2,41 +2,68 @@ package gothings import ( "cwtch.im/cwtch/model" + "cwtch.im/cwtch/protocol/connections" "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 Attributable interface { - GetAttribute(string) (string, bool) - SetAttribute(string, string) +func isGroup(id string) bool { + return len(id) == 32 +} + +func isPeer(id string) bool { + return len(id) == 56 +} + +func getWithSetDefault(id string, 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 { + 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(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)) - } +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)) return lastRead } -func updateLastReadTime(attr Attributable) { - lastRead := time.Now() - lastReadVal, _ := lastRead.MarshalText() - attr.SetAttribute(constants.LastRead, string(lastReadVal)) +func initProfilePicture(id string) string { + log.Infof("initProfilePic: %v\n", id) + if isGroup(id) { + return getWithSetDefault(id, constants.Picture, cwutil.RandomGroupImage(id)) + } else { + return getWithSetDefault(id, constants.Picture, cwutil.RandomProfileImage(id)) + } +} + +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)) + } } func countUnread(messages []model.Message, lastRead time.Time) int { @@ -53,11 +80,10 @@ func countUnread(messages []model.Message, lastRead time.Time) int { type InterfaceState struct { parentGcd *GrandCentralDispatcher - contacts sync.Map // string : *gobjects.Contact } func NewUIState(gcd *GrandCentralDispatcher) (uis InterfaceState) { - uis = InterfaceState{gcd, sync.Map{}} + uis = InterfaceState{gcd} return } @@ -65,96 +91,39 @@ func (this *InterfaceState) Acknowledge(mID string) { this.parentGcd.Acknowledged(mID) } -func (this *InterfaceState) AddContact(c *gobjects.Contact) { - if len(c.Handle) == 32 { // ADD GROUP - unread := 0 - group := the.Peer.GetGroup(c.Handle) +func (this *InterfaceState) AddContact(Handle string) { + if isGroup(Handle) { + group := the.Peer.GetGroup(Handle) if group != nil { - lastRead := initLastReadTime(group) - unread = countUnread(group.Timeline.GetMessages(), lastRead) - } - if _, found := this.contacts.Load(c.Handle); !found { - 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) + lastRead := initLastReadTime(group.GroupID) + unread := countUnread(group.Timeline.GetMessages(), lastRead) + picture := initProfilePicture(Handle) + nick, exists := group.GetAttribute(constants.Nick) + if !exists { + nick = Handle + } + + this.parentGcd.AddContact(Handle, nick, picture, group.GroupServer, unread, int(connections.ConnectionStateToType[group.State]), false, false) } return - } else if len(c.Handle) != 56 { - log.Errorf("sorry, unable to handle AddContact(%v)", c.Handle) + } else if !isPeer(Handle) { + log.Errorf("sorry, unable to handle AddContact(%v)", Handle) debug.PrintStack() return } - unread := 0 - contact := the.Peer.GetContact(c.Handle) + contact := the.Peer.GetContact(Handle) if contact != nil { - lastRead := initLastReadTime(contact) - unread = countUnread(contact.Timeline.GetMessages(), lastRead) - } - 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, unread, c.Status, c.Trusted, c.Blocked, false) - if the.Peer.GetContact(c.Handle) == nil { - the.Peer.AddContact(c.DisplayName, c.Handle, c.Trusted) - go the.Peer.PeerWithOnion(c.Handle) + lastRead := initLastReadTime(contact.Onion) + unread := countUnread(contact.Timeline.GetMessages(), lastRead) + picture := initProfilePicture(Handle) + nick, exists := contact.GetAttribute(constants.Nick) + if !exists { + nick = Handle } - } -} -func (this *InterfaceState) DeleteContact(id string) { - this.contacts.Delete(id) -} - -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(constants.Nick) - if !exists { - nick = group.GroupID[:12] - } - this.AddContact(&gobjects.Contact{ - handle, - nick, - cwutil.RandomGroupImage(handle), - group.GroupServer, - 0, - group.Accepted, - false, - false, - }) - } 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, - false, - contact.Blocked, - false, - }) - } else if contact == nil { - //log.Errorf("Attempting to add non existent contact to ui %v", handle) - } - } + this.parentGcd.AddContact(Handle, nick, picture, "", unread, int(connections.ConnectionStateToType[contact.State]), contact.Blocked, false) } - - 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) { @@ -165,11 +134,7 @@ func (this *InterfaceState) AddSendMessageError(peer string, signature string, e } func (this *InterfaceState) AddMessage(m *gobjects.Message) { - if len(m.Handle) == 32 { // GROUP - updateLastReadTime(the.Peer.GetGroup(m.Handle)) - } else { - updateLastReadTime(the.Peer.GetContact(m.Handle)) - } + updateLastReadTime(m.Handle) // If we have this group loaded already if this.parentGcd.CurrentOpenConversation() == m.Handle { @@ -184,17 +149,12 @@ func (this *InterfaceState) AddMessage(m *gobjects.Message) { } } -func (this *InterfaceState) UpdateContact(handle string) { - contact := the.Peer.GetContact(handle) - cif, found := this.contacts.Load(handle) - if found { - c := cif.(*gobjects.Contact) - if contact != nil { - c.Blocked = contact.Blocked - } - this.parentGcd.UpdateContact(c.Handle, c.DisplayName, c.Image, c.Server, c.Status, c.Trusted, c.Blocked, c.Loading) +func (this *InterfaceState) UpdateContactDisplayName(handle string, name string) { + this.parentGcd.UpdateContactDisplayName(handle, name) +} - } +func (this *InterfaceState) UpdateContactStatus(handle string, status int, loading bool) { + this.parentGcd.UpdateContactStatus(handle, status, loading) } func (this *InterfaceState) UpdateContactAttribute(handle, key, value string) { diff --git a/qml/overlays/BulletinOverlay.qml b/qml/overlays/BulletinOverlay.qml index c8abe9a6..f914acb6 100644 --- a/qml/overlays/BulletinOverlay.qml +++ b/qml/overlays/BulletinOverlay.qml @@ -87,12 +87,12 @@ ColumnLayout { }) } - if (sv.contentY + sv.height >= sv.contentHeight - colMessages.height && sv.contentHeight > sv.height) { + /*if (sv.contentY + sv.height >= sv.contentHeight - colMessages.height && sv.contentHeight > sv.height) { sv.contentY = sv.contentHeight - sv.height - } + }*/ } - onUpdateContact: function(_handle, _displayName, _image, _server, _status, _trusted, _blocked, _loading) { + onUpdateContactStatus: function(_handle, _status, _loading) { if (gcd.currentOpenConversation == _handle) { if (_loading == true) { newposttitle.enabled = false diff --git a/qml/overlays/ChatOverlay.qml b/qml/overlays/ChatOverlay.qml index 59dfefa4..b2c6d9ae 100644 --- a/qml/overlays/ChatOverlay.qml +++ b/qml/overlays/ChatOverlay.qml @@ -110,10 +110,10 @@ ColumnLayout { messagesListView.positionViewAtEnd() } - onUpdateContact: function(_handle, _displayName, _image, _server, _status, _trusted, _blocked, _loading) { + onUpdateContactStatus: function(_handle, _status, _loading) { if (gcd.currentOpenConversation == _handle) { // Group is Synced OR p2p is Authenticated - if ( (_handle.length == 32 && _status == 4) || _status == 3) { + if ( (_handle.length == 32 && _status == 4) || (_handle.length == 56 && _status == 3) ) { txtMessage.enabled = true btnSend.enabled = true } else { diff --git a/qml/overlays/ListOverlay.qml b/qml/overlays/ListOverlay.qml index 1515a4f1..6f983722 100644 --- a/qml/overlays/ListOverlay.qml +++ b/qml/overlays/ListOverlay.qml @@ -87,16 +87,16 @@ ColumnLayout { }) } - if(msg.c != undefined) { + /*if(msg.c != undefined) { jsonModel4.get(msg.c).complete = true } if (sv.contentY + sv.height >= sv.contentHeight - colMessages.height && sv.contentHeight > sv.height) { sv.contentY = sv.contentHeight - sv.height - } + }*/ } - onUpdateContact: function(_handle, _displayName, _image, _server, _status, _trusted, _blocked, _loading) { + onUpdateContactStatus: function(_handle, _status, _loading) { if (gcd.currentOpenConversation == _handle) { if (_loading == true) { newposttitle.enabled = false diff --git a/qml/overlays/MembershipOverlay.qml b/qml/overlays/MembershipOverlay.qml index d35caef8..b9297717 100644 --- a/qml/overlays/MembershipOverlay.qml +++ b/qml/overlays/MembershipOverlay.qml @@ -105,7 +105,6 @@ ColumnLayout { handle: _handle displayName: _displayName image: _image - trusted: true blocked: false background: false } diff --git a/qml/widgets/ContactList.qml b/qml/widgets/ContactList.qml index d13fdd3d..c0b81efc 100644 --- a/qml/widgets/ContactList.qml +++ b/qml/widgets/ContactList.qml @@ -47,7 +47,7 @@ ColumnLayout { Connections { // ADD/REMOVE CONTACT ENTRIES target: gcd - onAddContact: function(handle, displayName, image, server, badge, status, trusted, blocked, loading) { + onAddContact: function(handle, displayName, image, server, badge, status, blocked, loading) { contactsModel.append({ "_handle": handle, "_displayName": displayName + (blocked ? " (blocked)" : "" ), @@ -55,7 +55,6 @@ ColumnLayout { "_server": server, "_badge": badge, "_status": status, - "_trusted": trusted, "_blocked": blocked, "_loading": loading, "_loading": loading @@ -86,7 +85,6 @@ ColumnLayout { server: _server badge: _badge status: _status - trusted: _trusted blocked: _blocked loading: _loading } diff --git a/qml/widgets/ContactPicture.qml b/qml/widgets/ContactPicture.qml index 5281cdb3..42971be5 100644 --- a/qml/widgets/ContactPicture.qml +++ b/qml/widgets/ContactPicture.qml @@ -68,7 +68,7 @@ Item { anchors.margins: 4 * logscale - Rectangle { //-2:WtfCodeError,-1:Untrusted,0:Disconnected,1:Connecting,2:Connected,3:Authenticated,4:Synced,5:Failed,6:Killed + Rectangle { //-2:WtfCodeError,-1:Error,0:Disconnected,1:Connecting,2:Connected,3:Authenticated,4:Synced,5:Failed,6:Killed color: status == 4 ? "green" : status == 3 ? "green" : status == -1 ? "blue" : status == 1 ? "orange" : status == 2 ? "orange" : "red" width: 5 * logscale height: 5 * logscale diff --git a/qml/widgets/ContactRow.qml b/qml/widgets/ContactRow.qml index a3f3f9e9..5f497ec5 100644 --- a/qml/widgets/ContactRow.qml +++ b/qml/widgets/ContactRow.qml @@ -22,7 +22,6 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY property int badge property bool isActive property bool isHover - property bool trusted property bool blocked property bool loading property alias status: imgProfile.status @@ -52,7 +51,6 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY anchors.right: loading ? loadingProgress.left : rectUnread.left anchors.verticalCenter: parent.verticalCenter font.pixelSize: 16 * gcd.themeScale - font.italic: !trusted font.strikeout: blocked textFormat: Text.PlainText //fontSizeMode: Text.HorizontalFit @@ -146,17 +144,24 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY isActive = false } - onUpdateContact: function(_handle, _displayName, _image, _server, _status, _trusted, _blocked, _loading) { - if (handle == _handle) { - displayName = _displayName + (_blocked == true ? " (blocked)" : "") - image = _image - server = _server - status = _status - trusted = _trusted - blocked = _blocked + onUpdateContactStatus: function(_handle, _status, _loading) { + if (handle == _handle) { + status = _status loadingProgress.visible = loadingProgress.running = loading = _loading - } - } + } + } + + onUpdateContactBlocked: function(_handle, _blocked) { + if (handle == _handle) { + blocked = _blocked + } + } + + onUpdateContactDisplayName: function(_handle, _displayName) { + if (handle == _handle) { + displayName = _displayName + (_blocked == true ? " (blocked)" : "") + } + } onIncContactUnreadCount: function(handle) { if (handle == _handle) {