gcd and manager now lock gcd to qml ui events for non selected profile
the build was successful Details

This commit is contained in:
Dan Ballard 2019-11-19 13:36:28 -08:00
parent bac4accb1b
commit 7a7be2777b
11 changed files with 216 additions and 103 deletions

View File

@ -109,13 +109,13 @@ func App(gcd *ui.GrandCentralDispatcher, subscribed chan bool, reloadingFirst bo
}
log.Infof("NewPeer for %v\n", onion)
gcd.UIManager.AddProfile(onion)
ui.AddProfile(gcd, onion)
the.CwtchApp.AddPeerPlugin(onion, plugins.CONNECTIONRETRY)
the.CwtchApp.AddPeerPlugin(onion, plugins.NETWORKCHECK)
incSubscribed := make(chan bool)
go PeerHandler(onion, &gcd.UIManager, incSubscribed)
go PeerHandler(onion, gcd.GetUiManager(peer.GetProfile().Onion), incSubscribed)
<-incSubscribed
if e.Data[event.Status] != "running" {

View File

@ -9,7 +9,7 @@ import (
"time"
)
func PeerHandler(onion string, uiManager *ui.Manager, subscribed chan bool) {
func PeerHandler(onion string, uiManager ui.Manager, subscribed chan bool) {
peer := the.CwtchApp.GetPeer(onion)
eventBus := the.CwtchApp.GetEventBus(onion)
q := event.NewQueue()

View File

@ -5,6 +5,7 @@ import (
"cwtch.im/cwtch/protocol/connections"
"cwtch.im/ui/go/constants"
"github.com/therecipe/qt/qml"
"sync"
"cwtch.im/ui/go/the"
"encoding/base32"
@ -17,15 +18,21 @@ import (
type GrandCentralDispatcher struct {
core.QObject
UIManager Manager
QMLEngine *qml.QQmlApplicationEngine
Translator *core.QTranslator
uIManagers map[string]Manager
QMLEngine *qml.QQmlApplicationEngine
Translator *core.QTranslator
profileLock sync.Mutex
conversationLock sync.Mutex
m_selectedProfile string
m_selectedConversation string
_ string `property:"os"`
_ string `property:"currentOpenConversation"`
_ float32 `property:"themeScale"`
_ string `property:"version"`
_ string `property:"buildDate"`
_ string `property:"selectedProfile,auto"`
_ string `property:"selectedConversation,auto"`
// profile management stuff
_ func() `signal:"Loaded"`
@ -63,6 +70,8 @@ type GrandCentralDispatcher struct {
_ func(onion, nick string, blocked bool) `signal:"SupplyPeerSettings"`
// signals emitted from the ui (written in go, below)
//_ func(onion string) `signal:"setSelectedProfile,auto"`
//_ func(onion string) `signal:"setSelectedConversation,auto"`
_ func(message string, mid string) `signal:"sendMessage,auto"`
_ func(onion string) `signal:"blockPeer,auto"`
_ func(onion string) `signal:"unblockPeer,auto"`
@ -90,6 +99,78 @@ type GrandCentralDispatcher struct {
_ func() `signal:"onActivate,auto"`
_ func(password string) `signal:"unlockProfiles,auto"`
_ func(handle string) `signal:"loadProfile,auto"`
_ func() `constructor:"init"`
}
func (this *GrandCentralDispatcher) init() {
this.uIManagers = make(map[string]Manager)
}
func (this *GrandCentralDispatcher) GetUiManager(profile string) Manager {
this.profileLock.Lock()
defer this.profileLock.Unlock()
if manager, exists := this.uIManagers[profile]; exists {
return manager
} else {
this.uIManagers[profile] = NewManager(profile, this)
return this.uIManagers[profile]
}
}
func (this *GrandCentralDispatcher) selectedProfile() string {
this.profileLock.Lock()
defer this.profileLock.Unlock()
return this.m_selectedProfile
}
func (this *GrandCentralDispatcher) setSelectedProfile(onion string) {
this.profileLock.Lock()
defer this.profileLock.Unlock()
this.m_selectedProfile = onion
}
func (this *GrandCentralDispatcher) selectedProfileChanged(onion string) {
this.SelectedProfileChanged(onion)
}
func (this *GrandCentralDispatcher) DoIfProfile(profile string, fn func()) {
this.profileLock.Lock()
defer this.profileLock.Unlock()
if this.m_selectedProfile == profile {
fn()
}
}
func (this *GrandCentralDispatcher) selectedConversation() string {
this.conversationLock.Lock()
defer this.conversationLock.Unlock()
return this.m_selectedConversation
}
func (this *GrandCentralDispatcher) setSelectedConversation(handle string) {
this.conversationLock.Lock()
defer this.conversationLock.Unlock()
this.m_selectedConversation = handle
}
func (this *GrandCentralDispatcher) selectedConversationChanged(handle string) {
this.SelectedConversationChanged(handle)
}
func (this *GrandCentralDispatcher) DoIfConversation(conversation string, fn func()) {
this.conversationLock.Lock()
defer this.conversationLock.Unlock()
if this.m_selectedConversation == conversation {
fn()
}
}
func (this *GrandCentralDispatcher) sendMessage(message string, mID string) {
@ -98,14 +179,14 @@ func (this *GrandCentralDispatcher) sendMessage(message string, mID string) {
return
}
if this.CurrentOpenConversation() == "" {
if this.SelectedConversation() == "" {
this.InvokePopup("ui error")
return
}
if isGroup(this.CurrentOpenConversation()) {
if !the.Peer.GetGroup(this.CurrentOpenConversation()).Accepted {
err := the.Peer.AcceptInvite(this.CurrentOpenConversation())
if isGroup(this.SelectedConversation()) {
if !the.Peer.GetGroup(this.SelectedConversation()).Accepted {
err := the.Peer.AcceptInvite(this.SelectedConversation())
if err != nil {
log.Errorf("tried to mark a nonexistent group as existed. bad!")
return
@ -113,19 +194,19 @@ func (this *GrandCentralDispatcher) sendMessage(message string, mID string) {
}
var err error
mID, err = the.Peer.SendMessageToGroupTracked(this.CurrentOpenConversation(), message)
mID, err = the.Peer.SendMessageToGroupTracked(this.SelectedConversation(), message)
this.UIManager.AddMessage(this.CurrentOpenConversation(), "me", message, true, mID, time.Now(), false)
this.GetUiManager(this.selectedProfile()).AddMessage(this.SelectedConversation(), "me", message, true, mID, time.Now(), false)
if err != nil {
this.InvokePopup("failed to send message " + err.Error())
return
}
} else {
to := this.CurrentOpenConversation()
to := this.SelectedConversation()
mID = the.Peer.SendMessageToPeer(to, message)
this.UIManager.AddMessage(to, "me", message, true, mID, time.Now(), false)
this.GetUiManager(this.selectedProfile()).AddMessage(to, "me", message, true, mID, time.Now(), false)
}
}
@ -139,7 +220,7 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) {
return
}
this.ClearMessages()
this.SetCurrentOpenConversation(handle)
this.SetSelectedConversation(handle)
if isGroup(handle) { // LOAD GROUP
group := the.Peer.GetGroup(handle)
@ -245,17 +326,18 @@ func (this *GrandCentralDispatcher) saveSettings(zoom, locale string) {
}
func (this *GrandCentralDispatcher) requestPeerSettings() {
contact := the.Peer.GetContact(this.CurrentOpenConversation())
contact := the.Peer.GetContact(this.SelectedConversation())
if contact == nil {
log.Errorf("error: requested settings for unknown contact %v?", this.CurrentOpenConversation())
this.SupplyPeerSettings(this.CurrentOpenConversation(), this.CurrentOpenConversation(), false)
log.Errorf("error: requested settings for unknown contact %v?", this.SelectedConversation())
this.SupplyPeerSettings(this.SelectedConversation(), this.SelectedConversation(), false)
return
}
name, exists := contact.GetAttribute(constants.Nick)
if !exists {
log.Errorf("error: couldn't find contact %v", this.CurrentOpenConversation())
this.SupplyPeerSettings(this.CurrentOpenConversation(), this.CurrentOpenConversation(), contact.Blocked)
log.Errorf("error: couldn't find contact %v", this.SelectedConversation())
this.SupplyPeerSettings(this.SelectedConversation(), this.SelectedConversation(), contact.Blocked)
this.SupplyPeerSettings(this.SelectedConversation(), this.SelectedConversation(), contact.Blocked)
return
}
@ -379,7 +461,7 @@ func (this *GrandCentralDispatcher) importString(str string) {
the.Peer.PeerWithOnion(onion)
}
this.UIManager.AddContact(onion)
this.GetUiManager(this.selectedProfile()).AddContact(onion)
}
func (this *GrandCentralDispatcher) popup(str string) {
@ -400,7 +482,7 @@ func (this *GrandCentralDispatcher) createGroup(server, groupName string) {
return
}
this.UIManager.AddContact(groupID)
this.GetUiManager(this.selectedProfile()).AddContact(groupID)
the.Peer.SetGroupAttribute(groupID, constants.Nick, groupName)
@ -449,7 +531,7 @@ func (this *GrandCentralDispatcher) acceptGroup(groupID string) {
func (this *GrandCentralDispatcher) setAttribute(onion, key, value string) {
the.Peer.SetContactAttribute(onion, key, value)
this.UIManager.UpdateContactAttribute(onion, key, value)
this.GetUiManager(this.selectedProfile()).UpdateContactAttribute(onion, key, value)
}
func (this *GrandCentralDispatcher) blockUnknownPeers() {
@ -505,13 +587,13 @@ func (this *GrandCentralDispatcher) loadProfile(onion string) {
contacts := the.Peer.GetContacts()
for i := range contacts {
this.UIManager.AddContact(contacts[i])
this.GetUiManager(this.selectedProfile()).AddContact(contacts[i])
}
groups := the.Peer.GetGroups()
for i := range groups {
// Only join servers for active and explicitly accepted groups.
this.UIManager.AddContact(groups[i])
this.GetUiManager(this.selectedProfile()).AddContact(groups[i])
}
// load ui preferences

View File

@ -107,15 +107,7 @@ func countUnread(messages []model.Message, lastRead time.Time) int {
return count
}
type Manager struct {
gcd *GrandCentralDispatcher
}
func NewManager(gcd *GrandCentralDispatcher) Manager {
return Manager{gcd}
}
func (this *Manager) AddProfile(handle string) {
func AddProfile(gcd *GrandCentralDispatcher, handle string) {
peer := the.CwtchApp.GetPeer(handle)
if peer != nil {
nick := peer.GetProfile().Name
@ -130,12 +122,34 @@ func (this *Manager) AddProfile(handle string) {
peer.SetAttribute(constants.Picture, pic)
}
log.Infof("AddProfile %v %v %v\n", handle, nick, pic)
this.gcd.AddProfile(handle, nick, pic)
gcd.AddProfile(handle, nick, pic)
}
}
func (this *Manager) Acknowledge(mID string) {
this.gcd.Acknowledged(mID)
type manager struct {
gcd *GrandCentralDispatcher
profile string
}
type Manager interface {
Acknowledge(mID string)
AddContact(Handle string)
AddSendMessageError(peer string, signature string, err string)
AddMessage(handle string, from string, message string, fromMe bool, messageID string, timestamp time.Time, Acknowledged bool)
UpdateContactDisplayName(handle string, name string)
UpdateContactStatus(handle string, status int, loading bool)
UpdateContactAttribute(handle, key, value string)
}
func NewManager(profile string, gcd *GrandCentralDispatcher) Manager {
return &manager{gcd: gcd, profile: profile}
}
func (this *manager) Acknowledge(mID string) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.Acknowledged(mID)
})
}
func getLastMessageTime(tl *model.Timeline) int {
@ -146,77 +160,93 @@ func getLastMessageTime(tl *model.Timeline) int {
return int(tl.Messages[len(tl.Messages)-1].Timestamp.Unix())
}
func (this *Manager) AddContact(Handle string) {
if isGroup(Handle) {
group := the.Peer.GetGroup(Handle)
if group != nil {
lastRead := initLastReadTime(group.GroupID)
unread := countUnread(group.Timeline.GetMessages(), lastRead)
func (this *manager) AddContact(Handle string) {
this.gcd.DoIfProfile(this.profile, func() {
if isGroup(Handle) {
group := the.Peer.GetGroup(Handle)
if group != nil {
lastRead := initLastReadTime(group.GroupID)
unread := countUnread(group.Timeline.GetMessages(), lastRead)
picture := initProfilePicture(Handle)
nick, exists := group.GetAttribute(constants.Nick)
if !exists {
nick = Handle
}
this.gcd.AddContact(Handle, nick, picture, group.GroupServer, unread, int(connections.ConnectionStateToType[group.State]), false, false, getLastMessageTime(&group.Timeline))
}
return
} else if !isPeer(Handle) {
log.Errorf("sorry, unable to handle AddContact(%v)", Handle)
debug.PrintStack()
return
}
contact := the.Peer.GetContact(Handle)
if contact != nil {
lastRead := initLastReadTime(contact.Onion)
unread := countUnread(contact.Timeline.GetMessages(), lastRead)
picture := initProfilePicture(Handle)
nick, exists := group.GetAttribute(constants.Nick)
nick, exists := contact.GetAttribute(constants.Nick)
if !exists {
nick = Handle
}
this.gcd.AddContact(Handle, nick, picture, group.GroupServer, unread, int(connections.ConnectionStateToType[group.State]), false, false, getLastMessageTime(&group.Timeline))
this.gcd.AddContact(Handle, nick, picture, "", unread, int(connections.ConnectionStateToType[contact.State]), contact.Blocked, false, getLastMessageTime(&contact.Timeline))
}
return
} else if !isPeer(Handle) {
log.Errorf("sorry, unable to handle AddContact(%v)", Handle)
debug.PrintStack()
return
}
contact := the.Peer.GetContact(Handle)
if contact != nil {
lastRead := initLastReadTime(contact.Onion)
unread := countUnread(contact.Timeline.GetMessages(), lastRead)
picture := initProfilePicture(Handle)
nick, exists := contact.GetAttribute(constants.Nick)
if !exists {
nick = Handle
}
this.gcd.AddContact(Handle, nick, picture, "", unread, int(connections.ConnectionStateToType[contact.State]), contact.Blocked, false, getLastMessageTime(&contact.Timeline))
}
})
}
func (this *Manager) AddSendMessageError(peer string, signature string, err string) {
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.gcd.GroupSendError(signature, err)
func (this *manager) AddSendMessageError(peer string, signature string, err string) {
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
time.Sleep(time.Second * 1)
this.gcd.GroupSendError(signature, err)
})
})
}
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)
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() {
// If we have this group loaded already
if this.gcd.CurrentOpenConversation() == handle {
updateLastReadTime(handle)
// If the message is not from the user then add it, otherwise, just acknowledge.
if !fromMe {
this.gcd.AppendMessage(handle, from, nick, message, image, messageID, fromMe, timestamp.Format(constants.TIME_FORMAT), false, false)
} else {
if !Acknowledged {
nick := getOrDefault(handle, constants.Nick, handle)
image := getProfilePic(handle)
// If we have this group loaded already
this.gcd.DoIfConversation(handle, func() {
updateLastReadTime(handle)
// If the message is not from the user then add it, otherwise, just acknowledge.
if !fromMe {
this.gcd.AppendMessage(handle, from, nick, message, image, messageID, fromMe, timestamp.Format(constants.TIME_FORMAT), false, false)
} else {
this.gcd.Acknowledged(messageID)
if !Acknowledged {
this.gcd.AppendMessage(handle, from, nick, message, image, messageID, fromMe, timestamp.Format(constants.TIME_FORMAT), false, false)
} else {
this.gcd.Acknowledged(messageID)
}
}
}
}
this.gcd.IncContactUnreadCount(handle)
})
this.gcd.IncContactUnreadCount(handle)
})
}
func (this *Manager) UpdateContactDisplayName(handle string, name string) {
this.gcd.UpdateContactDisplayName(handle, name)
func (this *manager) UpdateContactDisplayName(handle string, name string) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.UpdateContactDisplayName(handle, name)
})
}
func (this *Manager) UpdateContactStatus(handle string, status int, loading bool) {
this.gcd.UpdateContactStatus(handle, status, loading)
func (this *manager) UpdateContactStatus(handle string, status int, loading bool) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.UpdateContactStatus(handle, status, loading)
})
}
func (this *Manager) UpdateContactAttribute(handle, key, value string) {
this.gcd.UpdateContactAttribute(handle, key, value)
func (this *manager) UpdateContactAttribute(handle, key, value string) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.UpdateContactAttribute(handle, key, value)
})
}

View File

@ -137,7 +137,6 @@ func mainUi(flagLocal bool, flagClientUI bool) {
gcd.SetVersion("development")
gcd.SetBuildDate("now")
}
gcd.UIManager = ui.NewManager(gcd)
//TODO: put theme stuff somewhere better
gcd.SetThemeScale(1.0)

View File

@ -93,7 +93,7 @@ ColumnLayout {
}
onUpdateContactStatus: function(_handle, _status, _loading) {
if (gcd.currentOpenConversation == _handle) {
if (gcd.selectedConversation == _handle) {
if (_loading == true) {
newposttitle.enabled = false
newpostbody.enabled = false

View File

@ -111,7 +111,7 @@ ColumnLayout {
}
onUpdateContactStatus: function(_handle, _status, _loading) {
if (gcd.currentOpenConversation == _handle) {
if (gcd.selectedConversation == _handle) {
// Group is Synced OR p2p is Authenticated
if ( (_handle.length == 32 && _status == 4) || (_handle.length == 56 && _status == 3) ) {
txtMessage.enabled = true

View File

@ -97,7 +97,7 @@ ColumnLayout {
}
onUpdateContactStatus: function(_handle, _status, _loading) {
if (gcd.currentOpenConversation == _handle) {
if (gcd.selectedConversation == _handle) {
if (_loading == true) {
newposttitle.enabled = false
btnSend.enabled = false

View File

@ -19,14 +19,14 @@ ColumnLayout {
StackToolbar {
id: toolbar
membership.visible: gcd.currentOpenConversation.length == 32
membership.visible: gcd.selectedConversation.length == 32
membership.onClicked: overlayStack.overlay = overlayStack.membershipOverlay
aux.onClicked: {
if (gcd.currentOpenConversation.length == 32) {
if (gcd.selectedConversation.length == 32) {
theStack.pane = theStack.groupProfilePane
gcd.requestGroupSettings(gcd.currentOpenConversation)
gcd.requestGroupSettings(gcd.selectedConversation)
} else {
theStack.pane = theStack.userProfilePane
gcd.requestPeerSettings()
@ -36,7 +36,7 @@ ColumnLayout {
}
RowLayout {
visible:!overlay.accepted && (gcd.currentOpenConversation.length == 32)
visible:!overlay.accepted && (gcd.selectedConversation.length == 32)
Text {
@ -49,8 +49,8 @@ ColumnLayout {
text: qsTr("accept-group-btn")
icon: "regular/heart"
onClicked: {
gcd.acceptGroup(gcd.currentOpenConversation)
gcd.requestGroupSettings(gcd.currentOpenConversation)
gcd.acceptGroup(gcd.selectedConversation)
gcd.requestGroupSettings(gcd.selectedConversation)
}
}
@ -59,7 +59,7 @@ ColumnLayout {
text: qsTr("reject-group-btn")
icon: "regular/trash-alt"
onClicked: {
gcd.leaveGroup(gcd.currentOpenConversation)
gcd.leaveGroup(gcd.selectedConversation)
theStack.pane = theStack.emptyPane
}
}

View File

@ -150,6 +150,7 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY
} else if (type == "profile") {
gcd.broadcast("ResetMessagePane")
gcd.broadcast("ResetProfile")
gcd.selectedProfile = handle
gcd.loadProfile(handle)
parentStack.pane = parentStack.profilePane
}
@ -191,7 +192,7 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY
}
onIncContactUnreadCount: function(handle) {
if (handle == _handle && gcd.currentOpenConversation != handle) {
if (handle == _handle && gcd.selectedConversation != handle) {
badge++
}
}

View File

@ -28,6 +28,7 @@ ColumnLayout {
anchors.top: parent.top
anchors.topMargin: 2
onClicked: function() {
gcd.selectedProfile = "none"
parentStack.pane = parentStack.managementPane
theStack.pane = theStack.emptyPane
}