Merge branch 'lockProfile' of dan/ui into master
the build was successful Details

This commit is contained in:
Sarah Jamie Lewis 2019-11-20 13:25:13 -08:00 committed by Gogs
commit 5df3fd4cf4
11 changed files with 233 additions and 101 deletions

View File

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

View File

@ -9,7 +9,7 @@ import (
"time" "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) peer := the.CwtchApp.GetPeer(onion)
eventBus := the.CwtchApp.GetEventBus(onion) eventBus := the.CwtchApp.GetEventBus(onion)
q := event.NewQueue() q := event.NewQueue()

View File

@ -5,6 +5,7 @@ import (
"cwtch.im/cwtch/protocol/connections" "cwtch.im/cwtch/protocol/connections"
"cwtch.im/ui/go/constants" "cwtch.im/ui/go/constants"
"github.com/therecipe/qt/qml" "github.com/therecipe/qt/qml"
"sync"
"cwtch.im/ui/go/the" "cwtch.im/ui/go/the"
"encoding/base32" "encoding/base32"
@ -17,15 +18,23 @@ import (
type GrandCentralDispatcher struct { type GrandCentralDispatcher struct {
core.QObject core.QObject
UIManager Manager
QMLEngine *qml.QQmlApplicationEngine QMLEngine *qml.QQmlApplicationEngine
Translator *core.QTranslator Translator *core.QTranslator
uIManagers map[string]Manager // profile-onion : Manager
profileLock sync.Mutex
conversationLock sync.Mutex
m_selectedProfile string
m_selectedConversation string
_ string `property:"os"` _ string `property:"os"`
_ string `property:"currentOpenConversation"`
_ float32 `property:"themeScale"` _ float32 `property:"themeScale"`
_ string `property:"version"` _ string `property:"version"`
_ string `property:"buildDate"` _ string `property:"buildDate"`
_ string `property:"selectedProfile,auto"`
_ string `property:"selectedConversation,auto"`
// profile management stuff // profile management stuff
_ func() `signal:"Loaded"` _ func() `signal:"Loaded"`
@ -90,6 +99,83 @@ type GrandCentralDispatcher struct {
_ func() `signal:"onActivate,auto"` _ func() `signal:"onActivate,auto"`
_ func(password string) `signal:"unlockProfiles,auto"` _ func(password string) `signal:"unlockProfiles,auto"`
_ func(handle string) `signal:"loadProfile,auto"` _ func(handle string) `signal:"loadProfile,auto"`
_ func() `constructor:"init"`
}
func (this *GrandCentralDispatcher) init() {
this.uIManagers = make(map[string]Manager)
}
// GetUiManager gets (and creates if required) a ui Manager for the supplied profile id
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)
}
// DoIfProfile performs a gcd action for a profile IF it is the currently selected profile in the UI
// otherwise it does nothing. it also locks profile switching for the duration of the action
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)
}
// DoIfConversation performs a gcd action for a conversation IF it is the currently selected conversation in the UI
// otherwise it does nothing. it also locks conversation switching for the duration of the action
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) { func (this *GrandCentralDispatcher) sendMessage(message string, mID string) {
@ -98,14 +184,14 @@ func (this *GrandCentralDispatcher) sendMessage(message string, mID string) {
return return
} }
if this.CurrentOpenConversation() == "" { if this.SelectedConversation() == "" {
this.InvokePopup("ui error") this.InvokePopup("ui error")
return return
} }
if isGroup(this.CurrentOpenConversation()) { if isGroup(this.SelectedConversation()) {
if !the.Peer.GetGroup(this.CurrentOpenConversation()).Accepted { if !the.Peer.GetGroup(this.SelectedConversation()).Accepted {
err := the.Peer.AcceptInvite(this.CurrentOpenConversation()) err := the.Peer.AcceptInvite(this.SelectedConversation())
if err != nil { if err != nil {
log.Errorf("tried to mark a nonexistent group as existed. bad!") log.Errorf("tried to mark a nonexistent group as existed. bad!")
return return
@ -113,19 +199,19 @@ func (this *GrandCentralDispatcher) sendMessage(message string, mID string) {
} }
var err error 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 { if err != nil {
this.InvokePopup("failed to send message " + err.Error()) this.InvokePopup("failed to send message " + err.Error())
return return
} }
} else { } else {
to := this.CurrentOpenConversation() to := this.SelectedConversation()
mID = the.Peer.SendMessageToPeer(to, message) 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 +225,7 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) {
return return
} }
this.ClearMessages() this.ClearMessages()
this.SetCurrentOpenConversation(handle) this.SetSelectedConversation(handle)
if isGroup(handle) { // LOAD GROUP if isGroup(handle) { // LOAD GROUP
group := the.Peer.GetGroup(handle) group := the.Peer.GetGroup(handle)
@ -245,17 +331,18 @@ func (this *GrandCentralDispatcher) saveSettings(zoom, locale string) {
} }
func (this *GrandCentralDispatcher) requestPeerSettings() { func (this *GrandCentralDispatcher) requestPeerSettings() {
contact := the.Peer.GetContact(this.CurrentOpenConversation()) contact := the.Peer.GetContact(this.SelectedConversation())
if contact == nil { if contact == nil {
log.Errorf("error: requested settings for unknown contact %v?", this.CurrentOpenConversation()) log.Errorf("error: requested settings for unknown contact %v?", this.SelectedConversation())
this.SupplyPeerSettings(this.CurrentOpenConversation(), this.CurrentOpenConversation(), false) this.SupplyPeerSettings(this.SelectedConversation(), this.SelectedConversation(), false)
return return
} }
name, exists := contact.GetAttribute(constants.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.SelectedConversation())
this.SupplyPeerSettings(this.CurrentOpenConversation(), this.CurrentOpenConversation(), contact.Blocked) this.SupplyPeerSettings(this.SelectedConversation(), this.SelectedConversation(), contact.Blocked)
this.SupplyPeerSettings(this.SelectedConversation(), this.SelectedConversation(), contact.Blocked)
return return
} }
@ -379,7 +466,7 @@ func (this *GrandCentralDispatcher) importString(str string) {
the.Peer.PeerWithOnion(onion) the.Peer.PeerWithOnion(onion)
} }
this.UIManager.AddContact(onion) this.GetUiManager(this.selectedProfile()).AddContact(onion)
} }
func (this *GrandCentralDispatcher) popup(str string) { func (this *GrandCentralDispatcher) popup(str string) {
@ -400,7 +487,7 @@ func (this *GrandCentralDispatcher) createGroup(server, groupName string) {
return return
} }
this.UIManager.AddContact(groupID) this.GetUiManager(this.selectedProfile()).AddContact(groupID)
the.Peer.SetGroupAttribute(groupID, constants.Nick, groupName) the.Peer.SetGroupAttribute(groupID, constants.Nick, groupName)
@ -449,7 +536,7 @@ func (this *GrandCentralDispatcher) acceptGroup(groupID string) {
func (this *GrandCentralDispatcher) setAttribute(onion, key, value string) { func (this *GrandCentralDispatcher) setAttribute(onion, key, value string) {
the.Peer.SetContactAttribute(onion, key, value) the.Peer.SetContactAttribute(onion, key, value)
this.UIManager.UpdateContactAttribute(onion, key, value) this.GetUiManager(this.selectedProfile()).UpdateContactAttribute(onion, key, value)
} }
func (this *GrandCentralDispatcher) blockUnknownPeers() { func (this *GrandCentralDispatcher) blockUnknownPeers() {
@ -505,13 +592,13 @@ func (this *GrandCentralDispatcher) loadProfile(onion string) {
contacts := the.Peer.GetContacts() contacts := the.Peer.GetContacts()
for i := range contacts { for i := range contacts {
this.UIManager.AddContact(contacts[i]) this.GetUiManager(this.selectedProfile()).AddContact(contacts[i])
} }
groups := the.Peer.GetGroups() groups := the.Peer.GetGroups()
for i := range groups { for i := range groups {
// Only join servers for active and explicitly accepted 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 // load ui preferences

View File

@ -107,15 +107,8 @@ func countUnread(messages []model.Message, lastRead time.Time) int {
return count return count
} }
type Manager struct { // AddProfile adds a new profile to the UI
gcd *GrandCentralDispatcher func AddProfile(gcd *GrandCentralDispatcher, handle string) {
}
func NewManager(gcd *GrandCentralDispatcher) Manager {
return Manager{gcd}
}
func (this *Manager) AddProfile(handle string) {
peer := the.CwtchApp.GetPeer(handle) peer := the.CwtchApp.GetPeer(handle)
if peer != nil { if peer != nil {
nick := peer.GetProfile().Name nick := peer.GetProfile().Name
@ -130,12 +123,41 @@ func (this *Manager) AddProfile(handle string) {
peer.SetAttribute(constants.Picture, pic) peer.SetAttribute(constants.Picture, pic)
} }
log.Infof("AddProfile %v %v %v\n", handle, nick, 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) { type manager struct {
this.gcd.Acknowledged(mID) gcd *GrandCentralDispatcher
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 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
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)
}
// 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}
}
// Acknowledge acknowledges the given message id in the UI
func (this *manager) Acknowledge(mID string) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.Acknowledged(mID)
})
} }
func getLastMessageTime(tl *model.Timeline) int { func getLastMessageTime(tl *model.Timeline) int {
@ -146,77 +168,99 @@ func getLastMessageTime(tl *model.Timeline) int {
return int(tl.Messages[len(tl.Messages)-1].Timestamp.Unix()) return int(tl.Messages[len(tl.Messages)-1].Timestamp.Unix())
} }
func (this *Manager) AddContact(Handle string) { // AddContact adds a new contact to the ui for this manager's profile
if isGroup(Handle) { func (this *manager) AddContact(Handle string) {
group := the.Peer.GetGroup(Handle) this.gcd.DoIfProfile(this.profile, func() {
if group != nil {
lastRead := initLastReadTime(group.GroupID) if isGroup(Handle) {
unread := countUnread(group.Timeline.GetMessages(), lastRead) 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) picture := initProfilePicture(Handle)
nick, exists := group.GetAttribute(constants.Nick) nick, exists := contact.GetAttribute(constants.Nick)
if !exists { if !exists {
nick = Handle 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) { // 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
log.Debugf("Received Error Sending Message: %v", err) func (this *manager) AddSendMessageError(peer string, signature string, err string) {
// FIXME: Sometimes, for the first Peer message we send our error beats our message to the UI this.gcd.DoIfProfile(this.profile, func() {
time.Sleep(time.Second * 1) this.gcd.DoIfConversation(peer, func() {
this.gcd.GroupSendError(signature, err) 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) { // AddMessage adds a message to the message pane for the supplied conversation if it is active
nick := getOrDefault(handle, constants.Nick, handle) func (this *manager) AddMessage(handle string, from string, message string, fromMe bool, messageID string, timestamp time.Time, Acknowledged bool) {
image := getProfilePic(handle) this.gcd.DoIfProfile(this.profile, func() {
// If we have this group loaded already nick := getOrDefault(handle, constants.Nick, handle)
if this.gcd.CurrentOpenConversation() == handle { image := getProfilePic(handle)
updateLastReadTime(handle)
// If the message is not from the user then add it, otherwise, just acknowledge. // If we have this group loaded already
if !fromMe { this.gcd.DoIfConversation(handle, func() {
this.gcd.AppendMessage(handle, from, nick, message, image, messageID, fromMe, timestamp.Format(constants.TIME_FORMAT), false, false) updateLastReadTime(handle)
} else { // If the message is not from the user then add it, otherwise, just acknowledge.
if !Acknowledged { if !fromMe {
this.gcd.AppendMessage(handle, from, nick, message, image, messageID, fromMe, timestamp.Format(constants.TIME_FORMAT), false, false) this.gcd.AppendMessage(handle, from, nick, message, image, messageID, fromMe, timestamp.Format(constants.TIME_FORMAT), false, false)
} else { } 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) { // UpdateContactDisplayName updates a contact's display name in the contact list and conversations
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) { // UpdateContactStatus updates a contact's status in the ui
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) { // UpdateContactAttribute update's a contacts attribute in the ui
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.SetVersion("development")
gcd.SetBuildDate("now") gcd.SetBuildDate("now")
} }
gcd.UIManager = ui.NewManager(gcd)
//TODO: put theme stuff somewhere better //TODO: put theme stuff somewhere better
gcd.SetThemeScale(1.0) gcd.SetThemeScale(1.0)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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