From 672570ed42991c435a46e37f270fee89b002e4c6 Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Wed, 24 Apr 2019 13:32:20 -0700 Subject: [PATCH] display progress of group loading and disable sending to groups until loaded --- go/characters/incominglistener.go | 30 +++++---- go/characters/presencepoller.go | 3 +- go/gobjects/contact.go | 1 + go/gothings/gcd.go | 101 +++++++++++++++--------------- go/gothings/uistate.go | 59 ++++++++++------- main.go | 4 +- qml/main.qml | 2 + qml/overlays/BulletinOverlay.qml | 15 +++++ qml/overlays/ChatOverlay.qml | 15 ++++- qml/overlays/ListOverlay.qml | 13 ++++ qml/panes/SplashPane.qml | 8 ++- qml/styles/CwtchProgress.qml | 10 ++- qml/widgets/ContactList.qml | 8 ++- qml/widgets/ContactRow.qml | 46 +++++++++++++- qml/widgets/MyProfile.qml | 1 + 15 files changed, 215 insertions(+), 101 deletions(-) diff --git a/go/characters/incominglistener.go b/go/characters/incominglistener.go index 2c1b10bd..41a9332f 100644 --- a/go/characters/incominglistener.go +++ b/go/characters/incominglistener.go @@ -11,19 +11,21 @@ import ( "time" ) -func IncomingListener(callback func(*gobjects.Message), groupErrorCallback func(string, string,string)) { +func IncomingListener(callback func(*gobjects.Message), groupErrorCallback func(string, string, string), serverStateCallback func(string, bool)) { q := event.NewEventQueue(1000) the.CwtchApp.EventBus().Subscribe(event.NewMessageFromPeer, q.EventChannel) the.CwtchApp.EventBus().Subscribe(event.NewMessageFromGroup, q.EventChannel) the.CwtchApp.EventBus().Subscribe(event.NewGroupInvite, q.EventChannel) the.CwtchApp.EventBus().Subscribe(event.SendMessageToGroupError, q.EventChannel) the.CwtchApp.EventBus().Subscribe(event.SendMessageToPeerError, q.EventChannel) + the.CwtchApp.EventBus().Subscribe(event.JoinServer, q.EventChannel) + the.CwtchApp.EventBus().Subscribe(event.FinishedFetch, q.EventChannel) for { e := q.Next() switch e.EventType { - case event.NewMessageFromPeer://event.TimestampReceived, event.RemotePeer, event.Data + case event.NewMessageFromPeer: //event.TimestampReceived, event.RemotePeer, event.Data ts, _ := time.Parse(time.RFC3339Nano, e.Data[event.TimestampReceived]) callback(&gobjects.Message{ Handle: e.Data[event.RemotePeer], @@ -40,7 +42,7 @@ func IncomingListener(callback func(*gobjects.Message), groupErrorCallback func( if e.Data[event.Data] != "ack" { the.Peer.SendMessageToPeer(e.Data[event.RemotePeer], "ack") } - case event.NewMessageFromGroup://event.TimestampReceived, event.TimestampSent, event.Data, event.GroupID, event.RemotePeer + case event.NewMessageFromGroup: //event.TimestampReceived, event.TimestampSent, event.Data, event.GroupID, event.RemotePeer var name string var exists bool ctc := the.Peer.GetContact(e.Data[event.RemotePeer]) @@ -55,15 +57,15 @@ func IncomingListener(callback func(*gobjects.Message), groupErrorCallback func( ts, _ := time.Parse(time.RFC3339Nano, e.Data[event.TimestampSent]) callback(&gobjects.Message{ - MessageID: e.Data[event.Signature], - Handle: e.Data[event.GroupID], - From: e.Data[event.RemotePeer], - Message: e.Data[event.Data], - Image: cwutil.RandomProfileImage(e.Data[event.RemotePeer]), - FromMe: e.Data[event.RemotePeer] == the.Peer.GetProfile().Onion, - Timestamp: ts, + MessageID: e.Data[event.Signature], + Handle: e.Data[event.GroupID], + From: e.Data[event.RemotePeer], + Message: e.Data[event.Data], + Image: cwutil.RandomProfileImage(e.Data[event.RemotePeer]), + FromMe: e.Data[event.RemotePeer] == the.Peer.GetProfile().Onion, + Timestamp: ts, Acknowledged: true, - DisplayName: name, + DisplayName: name, }) case event.NewGroupInvite: log.Debugf("got a group invite!") @@ -71,6 +73,10 @@ func IncomingListener(callback func(*gobjects.Message), groupErrorCallback func( groupErrorCallback(e.Data[event.GroupServer], e.Data[event.Signature], e.Data[event.Error]) case event.SendMessageToPeerError: groupErrorCallback(e.Data[event.RemotePeer], e.Data[event.Signature], e.Data[event.Error]) + case event.JoinServer: + serverStateCallback(e.Data[event.GroupServer], true) + case event.FinishedFetch: + serverStateCallback(e.Data[event.GroupServer], false) } } -} \ No newline at end of file +} diff --git a/go/characters/presencepoller.go b/go/characters/presencepoller.go index 034f31e3..ef011eb5 100644 --- a/go/characters/presencepoller.go +++ b/go/characters/presencepoller.go @@ -17,7 +17,7 @@ func PresencePoller(getContact func(string) *gobjects.Contact, addContact func(c if ct == nil { // new contact has attempted to connect with us, treat it as an invite toc := the.Peer.GetContact(contacts[i]) c, _ := the.Peer.GetProfile().GetContact(contacts[i]) - deleted,_ := c.GetAttribute("deleted") + deleted, _ := c.GetAttribute("deleted") if deleted != "deleted" { addContact(&gobjects.Contact{ @@ -28,6 +28,7 @@ func PresencePoller(getContact func(string) *gobjects.Contact, addContact func(c 0, 0, c.Trusted, + false, }) the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetPeerAttribute, map[event.Field]string{ diff --git a/go/gobjects/contact.go b/go/gobjects/contact.go index a86b5832..6493f19c 100644 --- a/go/gobjects/contact.go +++ b/go/gobjects/contact.go @@ -8,4 +8,5 @@ type Contact struct { Badge int Status int Trusted bool + Loading bool } diff --git a/go/gothings/gcd.go b/go/gothings/gcd.go index 206a9e17..86540a35 100644 --- a/go/gothings/gcd.go +++ b/go/gothings/gcd.go @@ -30,48 +30,49 @@ type GrandCentralDispatcher struct { _ string `property:"buildDate"` // contact list stuff - _ func(handle, displayName, image, server string, badge, status int, trusted bool) `signal:"AddContact"` - _ func(handle, displayName, image, server string, badge, status int, trusted bool) `signal:"UpdateContact"` - _ func(handle, key, value string) `signal:"UpdateContactAttribute"` + _ func(handle, displayName, image, server string, badge, status int, trusted bool, loading bool) `signal:"AddContact"` + _ func(handle, displayName, image, server string, badge, status int, trusted bool, loading bool) `signal:"UpdateContact"` + _ 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"` _ func(handle, from, displayName, message, image string, mID string, fromMe bool, ts string, ackd bool, error bool) `signal:"PrependMessage"` - _ func() `signal:"ClearMessages"` - _ func() `signal:"ResetMessagePane"` - _ func(mID string) `signal:"Acknowledged"` - _ func(title string) `signal:"SetToolbarTitle"` - _ func(signature string, err string) `signal:"GroupSendError"` + _ func() `signal:"ClearMessages"` + _ func() `signal:"ResetMessagePane"` + _ func(mID string) `signal:"Acknowledged"` + _ func(title string) `signal:"SetToolbarTitle"` + _ func(signature string, err string) `signal:"GroupSendError"` + _ func(loading bool) `signal:"SetLoadingState"` // profile-area stuff _ func(name, onion, image string) `signal:"UpdateMyProfile"` _ func(status int, str string) `signal:"TorStatus"` // settings helpers - _ func(str string) `signal:"InvokePopup"` - _ func(zoom, locale string) `signal:"SupplySettings"` + _ func(str string) `signal:"InvokePopup"` + _ func(zoom, locale string) `signal:"SupplySettings"` _ func(groupID, name, server, invitation string, accepted bool, addrbooknames, addrbookaddrs []string) `signal:"SupplyGroupSettings"` - _ func(onion, nick string) `signal:"SupplyPeerSettings"` + _ func(onion, nick string) `signal:"SupplyPeerSettings"` // signals emitted from the ui (written in go, below) _ func(message string, mid string) `signal:"sendMessage,auto"` - _ func(onion string) `signal:"loadMessagesPane,auto"` - _ func(signal string) `signal:"broadcast,auto"` // convenience relay signal - _ func(str string) `signal:"importString,auto"` - _ func(str string) `signal:"popup,auto"` - _ func(nick string) `signal:"updateNick,auto"` - _ func(server, groupName string) `signal:"createGroup,auto"` - _ func(groupID string) `signal:"leaveGroup,auto"` - _ func(groupID string) `signal:"acceptGroup,auto"` - _ func() `signal:"requestSettings,auto"` - _ func(zoom, locale string) `signal:"saveSettings,auto"` - _ func(groupID string) `signal:"requestGroupSettings,auto"` - _ func(groupID, nick string) `signal:"saveGroupSettings,auto"` - _ func() `signal:"requestPeerSettings,auto"` - _ func(onion, nick string) `signal:"savePeerSettings,auto"` - _ func(onion, groupID string) `signal:"inviteToGroup,auto"` - _ func(onion, key, nick string) `signal:"setAttribute,auto"` - _ func(locale string) `signal:"setLocale,auto"` + _ func(onion string) `signal:"loadMessagesPane,auto"` + _ func(signal string) `signal:"broadcast,auto"` // convenience relay signal + _ func(str string) `signal:"importString,auto"` + _ func(str string) `signal:"popup,auto"` + _ func(nick string) `signal:"updateNick,auto"` + _ func(server, groupName string) `signal:"createGroup,auto"` + _ func(groupID string) `signal:"leaveGroup,auto"` + _ func(groupID string) `signal:"acceptGroup,auto"` + _ func() `signal:"requestSettings,auto"` + _ func(zoom, locale string) `signal:"saveSettings,auto"` + _ func(groupID string) `signal:"requestGroupSettings,auto"` + _ func(groupID, nick string) `signal:"saveGroupSettings,auto"` + _ func() `signal:"requestPeerSettings,auto"` + _ func(onion, nick string) `signal:"savePeerSettings,auto"` + _ func(onion, groupID string) `signal:"inviteToGroup,auto"` + _ func(onion, key, nick string) `signal:"setAttribute,auto"` + _ func(locale string) `signal:"setLocale,auto"` } func (this *GrandCentralDispatcher) sendMessage(message string, mID string) { @@ -98,7 +99,7 @@ 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.CurrentOpenConversation(), message) this.UIState.AddMessage(&gobjects.Message{ this.CurrentOpenConversation(), @@ -114,7 +115,7 @@ func (this *GrandCentralDispatcher) sendMessage(message string, mID string) { }) if err != nil { - this.InvokePopup("failed to send message " +err.Error()) + this.InvokePopup("failed to send message " + err.Error()) return } } else { @@ -125,7 +126,7 @@ func (this *GrandCentralDispatcher) sendMessage(message string, mID string) { this.UIState.UpdateContact(this.CurrentOpenConversation()) } - to := this.CurrentOpenConversation(); + to := this.CurrentOpenConversation() the.Peer.PeerWithOnion(to) mID = the.Peer.SendMessageToPeer(to, message) @@ -148,7 +149,6 @@ func (this *GrandCentralDispatcher) sendMessage(message string, mID string) { the.AcknowledgementIDs[to] = append(the.AcknowledgementIDs[to], ackID) } - } func (this *GrandCentralDispatcher) loadMessagesPane(handle string) { @@ -169,15 +169,13 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) { 0, 0, false, + false, }) } else { c.Badge = 0 this.UIState.UpdateContact(handle) } - - - if len(handle) == 32 { // LOAD GROUP group := the.Peer.GetGroup(handle) tl := group.GetTimeline() @@ -212,9 +210,9 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) { string(tl[i].Signature), tl[i].PeerID == the.Peer.GetProfile().Onion, tl[i].Timestamp.Format(constants.TIME_FORMAT), - tl[i].Received.Equal(time.Unix(0,0)) == false, // If the received timestamp is epoch, we have not yet received this message through an active server + tl[i].Received.Equal(time.Unix(0, 0)) == false, // If the received timestamp is epoch, we have not yet received this message through an active server false, - ) + ) } return } // ELSE LOAD CONTACT @@ -248,7 +246,7 @@ func (this *GrandCentralDispatcher) loadMessagesPaneHelper(handle string) { false, messages[i].Error, ) - for _,id := range the.AcknowledgementIDs[messages[i].Handle] { + for _, id := range the.AcknowledgementIDs[messages[i].Handle] { if id.ID == messages[i].MessageID && id.Ack && !id.Error { this.Acknowledged(id.ID) } @@ -270,7 +268,7 @@ func (this *GrandCentralDispatcher) saveSettings(zoom, locale string) { } the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetAttribute, map[event.Field]string{ - event.Key: "settings.zoom", + event.Key: "settings.zoom", event.Data: zoom, })) } @@ -303,8 +301,8 @@ func (this *GrandCentralDispatcher) savePeerSettings(onion, nick string) { contact.SetAttribute("nick", nick) the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetPeerAttribute, map[event.Field]string{ event.RemotePeer: onion, - event.Key: "nick", - event.Data: nick, + event.Key: "nick", + event.Data: nick, })) this.UIState.contacts[onion].DisplayName = nick @@ -347,8 +345,8 @@ func (this *GrandCentralDispatcher) saveGroupSettings(groupID, nick string) { group.SetAttribute("nick", nick) the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetGroupAttribute, map[event.Field]string{ event.GroupID: groupID, - event.Key: "nick", - event.Data: nick, + event.Key: "nick", + event.Data: nick, })) this.UIState.contacts[groupID].DisplayName = nick @@ -420,7 +418,7 @@ func (this *GrandCentralDispatcher) importString(str string) { checkc := the.Peer.GetContact(onion) if checkc != nil { - deleted,_ := checkc.GetAttribute("deleted") + deleted, _ := checkc.GetAttribute("deleted") if deleted != "deleted" { this.InvokePopup("already have this contact") return //TODO: bring them to the duplicate @@ -466,8 +464,8 @@ func (this *GrandCentralDispatcher) createGroup(server, groupName string) { group.SetAttribute("nick", groupName) the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetGroupAttribute, map[event.Field]string{ event.GroupID: groupID, - event.Key: "nick", - event.Data: groupName, + event.Key: "nick", + event.Data: groupName, })) the.Peer.JoinServer(server) @@ -492,19 +490,18 @@ func (this *GrandCentralDispatcher) leaveGroup(groupID string) { func (this *GrandCentralDispatcher) acceptGroup(groupID string) { if the.Peer.GetGroup(groupID) != nil { the.Peer.AcceptInvite(groupID) - the.Peer.JoinServer(the.Peer.GetGroup(groupID).GroupServer) this.UIState.UpdateContact(groupID) } } func (this *GrandCentralDispatcher) setAttribute(onion, key, value string) { - pp,_ := the.Peer.GetProfile().GetContact(onion) + pp, _ := the.Peer.GetProfile().GetContact(onion) if pp != nil { pp.SetAttribute(key, value) the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetPeerAttribute, map[event.Field]string{ event.RemotePeer: onion, - event.Key: key, - event.Data: value, + event.Key: key, + event.Data: value, })) this.UIState.UpdateContactAttribute(onion, key, value) } @@ -514,7 +511,7 @@ func (this *GrandCentralDispatcher) setLocale(locale string) { this.SetLocale_helper(locale) the.CwtchApp.EventBus().Publish(event.NewEvent(event.SetAttribute, map[event.Field]string{ - event.Key: "settings.locale", + event.Key: "settings.locale", event.Data: locale, })) @@ -527,4 +524,4 @@ func (this *GrandCentralDispatcher) SetLocale_helper(locale string) { this.Translator.Load("translation_"+locale, ":/i18n/", "", "") core.QCoreApplication_InstallTranslator(this.Translator) this.QMLEngine.Retranslate() -} \ No newline at end of file +} diff --git a/go/gothings/uistate.go b/go/gothings/uistate.go index f90a5334..f4ccc3c1 100644 --- a/go/gothings/uistate.go +++ b/go/gothings/uistate.go @@ -27,7 +27,7 @@ func NewUIState(gcd *GrandCentralDispatcher) (uis InterfaceState) { func (this *InterfaceState) AddContact(c *gobjects.Contact) { if len(c.Handle) == 32 { // ADD GROUP if _, found := this.contacts[c.Handle]; !found { - this.parentGcd.AddContact(c.Handle, c.DisplayName, c.Image, c.Server, c.Badge, c.Status, c.Trusted) + this.parentGcd.AddContact(c.Handle, c.DisplayName, c.Image, c.Server, c.Badge, c.Status, c.Trusted, c.Loading) this.contacts[c.Handle] = c } return @@ -39,7 +39,7 @@ func (this *InterfaceState) AddContact(c *gobjects.Contact) { if _, found := this.contacts[c.Handle]; !found { this.contacts[c.Handle] = c - this.parentGcd.AddContact(c.Handle, c.DisplayName, c.Image, c.Server, c.Badge, c.Status, c.Trusted) + this.parentGcd.AddContact(c.Handle, c.DisplayName, c.Image, c.Server, c.Badge, c.Status, c.Trusted, false) if the.Peer.GetContact(c.Handle) == nil { decodedPub, _ := base32.StdEncoding.DecodeString(strings.ToUpper(c.Handle)) the.Peer.AddContact(c.DisplayName, c.Handle, decodedPub, c.Trusted) @@ -61,6 +61,7 @@ func (this *InterfaceState) GetContact(handle string) *gobjects.Contact { 0, 0, group.Accepted, + false, }) go the.Peer.JoinServer(group.GroupServer) @@ -70,15 +71,16 @@ func (this *InterfaceState) GetContact(handle string) *gobjects.Contact { } else { contact := the.Peer.GetContact(handle) if contact != nil && handle != contact.Onion { - this.AddContact(&gobjects.Contact{ - handle, - handle, - cwutil.RandomProfileImage(handle), - "", - 0, - 0, - false, - }) + this.AddContact(&gobjects.Contact{ + handle, + handle, + cwutil.RandomProfileImage(handle), + "", + 0, + 0, + false, + false, + }) } else if contact == nil { //log.Errorf("Attempting to add non existent contact to ui %v", handle) } @@ -90,29 +92,29 @@ func (this *InterfaceState) GetContact(handle string) *gobjects.Contact { func (this *InterfaceState) AddSendMessageError(peer string, signature string, err string) { acklist := the.AcknowledgementIDs[peer] - for _,ack := range acklist { + for _, ack := range acklist { if ack.ID == signature { ack.Error = true } } - messages,_ := this.messages.Load(peer) - messageList,_ := messages.([]*gobjects.Message) + messages, _ := this.messages.Load(peer) + messageList, _ := messages.([]*gobjects.Message) - for _,message := range messageList { + for _, message := range messageList { if message.MessageID == signature { message.Error = true } } 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) + time.Sleep(time.Second * 1) this.parentGcd.GroupSendError(signature, err) } func (this *InterfaceState) AddMessage(m *gobjects.Message) { this.GetContact(m.From) - _,found := this.messages.Load(m.Handle) + _, found := this.messages.Load(m.Handle) if !found { this.messages.Store(m.Handle, make([]*gobjects.Message, 0)) } @@ -125,7 +127,7 @@ func (this *InterfaceState) AddMessage(m *gobjects.Message) { if m.Message == "ack" { // If an ack, swallow the message and ack from the list. acklist := the.AcknowledgementIDs[m.From] - for _,ack := range acklist { + for _, ack := range acklist { if ack.Error == false { ack.Ack = true this.parentGcd.Acknowledged(ack.ID) @@ -133,8 +135,8 @@ func (this *InterfaceState) AddMessage(m *gobjects.Message) { } } else { - messages,_ := this.messages.Load(m.Handle) - messageList,_ := messages.([]*gobjects.Message) + messages, _ := this.messages.Load(m.Handle) + messageList, _ := messages.([]*gobjects.Message) this.messages.Store(m.Handle, append(messageList, m)) // If we have this group loaded already @@ -157,22 +159,31 @@ func (this *InterfaceState) AddMessage(m *gobjects.Message) { } func (this *InterfaceState) GetMessages(handle string) []*gobjects.Message { - _,found := this.messages.Load(handle) + _, found := this.messages.Load(handle) if !found { this.messages.Store(handle, make([]*gobjects.Message, 0)) } - messages,found := this.messages.Load(handle) - messageList,_ := messages.([]*gobjects.Message) + messages, found := this.messages.Load(handle) + messageList, _ := messages.([]*gobjects.Message) return messageList } func (this *InterfaceState) UpdateContact(handle string) { c, found := this.contacts[handle] if found { - this.parentGcd.UpdateContact(c.Handle, c.DisplayName, c.Image, c.Server, c.Badge, c.Status, c.Trusted) + this.parentGcd.UpdateContact(c.Handle, c.DisplayName, c.Image, c.Server, c.Badge, c.Status, c.Trusted, c.Loading) } } func (this *InterfaceState) UpdateContactAttribute(handle, key, value string) { this.parentGcd.UpdateContactAttribute(handle, key, value) } + +func (this *InterfaceState) UpdateServerStatus(server string, loading bool) { + for _, contact := range this.contacts { + if contact.Server == server { + contact.Loading = loading + this.UpdateContact(contact.Handle) + } + } +} diff --git a/main.go b/main.go index cf0e1980..191cef62 100644 --- a/main.go +++ b/main.go @@ -167,7 +167,7 @@ func loadNetworkingAndFiles(gcd *gothings.GrandCentralDispatcher) { // these are long-lived pollers/listeners for incoming messages and status changes loadCwtchData(gcd, the.ACN) - go characters.IncomingListener(gcd.UIState.AddMessage, gcd.UIState.AddSendMessageError) + go characters.IncomingListener(gcd.UIState.AddMessage, gcd.UIState.AddSendMessageError, gcd.UIState.UpdateServerStatus) go characters.TorStatusPoller(gcd.TorStatus, the.ACN) go characters.PresencePoller(gcd.UIState.GetContact, gcd.UIState.AddContact, gcd.UIState.UpdateContact) go characters.GroupPoller(gcd.UIState.GetContact, gcd.UIState.UpdateContact) @@ -227,6 +227,7 @@ func loadCwtchData(gcd *gothings.GrandCentralDispatcher, acn connectivity.ACN) { DisplayName: displayName, Image: cwutil.RandomProfileImage(contacts[i]), Trusted: contact.Trusted, + Loading: false, }) } } @@ -248,6 +249,7 @@ func loadCwtchData(gcd *gothings.GrandCentralDispatcher, acn connectivity.ACN) { Image: cwutil.RandomGroupImage(group.GroupID), Server: group.GroupServer, Trusted: group.Accepted, + Loading: true, }) // Only send a join server packet if we haven't joined this server yet... diff --git a/qml/main.qml b/qml/main.qml index 389ca411..116da994 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -125,7 +125,9 @@ ApplicationWindow { visible: true SplashPane { + id: splashPane anchors.fill: parent + running: true } } diff --git a/qml/overlays/BulletinOverlay.qml b/qml/overlays/BulletinOverlay.qml index d53bad56..cdb2afdf 100644 --- a/qml/overlays/BulletinOverlay.qml +++ b/qml/overlays/BulletinOverlay.qml @@ -91,6 +91,21 @@ ColumnLayout { sv.contentY = sv.contentHeight - sv.height } } + + onUpdateContact: function(_handle, _displayName, _image, _server, _badge, _status, _trusted, _loading) { + if (gcd.currentOpenConversation == _handle) { + if (_loading == true) { + newposttitle.enabled = false + newpostbody.enabled = false + btnSend.enabled = false + } else { + newposttitle.enabled = true + newpostbody.enabled = true + btnSend.enabled = true + } + + } + } } ScrollBar.vertical: ScrollBar{ diff --git a/qml/overlays/ChatOverlay.qml b/qml/overlays/ChatOverlay.qml index ac2986f4..4e9a829f 100644 --- a/qml/overlays/ChatOverlay.qml +++ b/qml/overlays/ChatOverlay.qml @@ -11,7 +11,7 @@ import "../utils.js" as Utils ColumnLayout { Layout.fillWidth: true - + property bool loading ListModel { // MESSAGE OBJECTS ARE STORED HERE ... id: messagesModel @@ -108,6 +108,19 @@ ColumnLayout { messagesListView.positionViewAtEnd() } + + onUpdateContact: function(_handle, _displayName, _image, _server, _badge, _status, _trusted, _loading) { + if (gcd.currentOpenConversation == _handle) { + if (_loading == true) { + txtMessage.enabled = false + btnSend.enabled = false + } else { + txtMessage.enabled = true + btnSend.enabled = true + } + + } + } } } diff --git a/qml/overlays/ListOverlay.qml b/qml/overlays/ListOverlay.qml index dde14cb0..1142f0ca 100644 --- a/qml/overlays/ListOverlay.qml +++ b/qml/overlays/ListOverlay.qml @@ -95,6 +95,19 @@ ColumnLayout { sv.contentY = sv.contentHeight - sv.height } } + + onUpdateContact: function(_handle, _displayName, _image, _server, _badge, _status, _trusted, _loading) { + if (gcd.currentOpenConversation == _handle) { + if (_loading == true) { + newposttitle.enabled = false + btnSend.enabled = false + } else { + newposttitle.enabled = true + btnSend.enabled = true + } + + } + } } ScrollBar.vertical: ScrollBar{ diff --git a/qml/panes/SplashPane.qml b/qml/panes/SplashPane.qml index 0a503411..478a080e 100644 --- a/qml/panes/SplashPane.qml +++ b/qml/panes/SplashPane.qml @@ -8,6 +8,9 @@ import QtQuick.Controls.Styles 1.4 import "../styles" Item { + id: sp + property bool running + Image { id: splashImage anchors.horizontalCenter: parent.horizontalCenter @@ -17,14 +20,17 @@ Item { } ProgressBar { + id: progressBar anchors.horizontalCenter: parent.horizontalCenter anchors.top: splashImage.bottom anchors.topMargin: 10 + width: splashImage.width indeterminate: true style: ProgressBarStyle { - progress: CwtchProgress {} + progress: CwtchProgress { running: sp.running } + } } } diff --git a/qml/styles/CwtchProgress.qml b/qml/styles/CwtchProgress.qml index 63fe59b7..9972eddc 100644 --- a/qml/styles/CwtchProgress.qml +++ b/qml/styles/CwtchProgress.qml @@ -8,8 +8,12 @@ import QtQuick.Controls.Styles 1.4 Rectangle { - border.color: "#D2C0DD" - color: "red" + id: pb + border.color: "#FFFFFF" + border.width: 1 + + color: "#D2C0DD" + property bool running // Indeterminate animation by animating alternating stripes: Item { @@ -28,7 +32,7 @@ Rectangle { XAnimator on x { from: 0 ; to: -40 loops: Animation.Infinite - running: parentStack.currentIndex == 0 + running: pb.running } } } diff --git a/qml/widgets/ContactList.qml b/qml/widgets/ContactList.qml index 8e7a2d72..3f37a053 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) { + onAddContact: function(handle, displayName, image, server, badge, status, trusted, loading) { contactsModel.append({ "_handle": handle, "_displayName": displayName, @@ -56,7 +56,8 @@ ColumnLayout { "_badge": badge, "_status": status, "_trusted": trusted, - "_deleted": false + "_deleted": false, + "_loading": loading }) } @@ -88,8 +89,9 @@ ColumnLayout { status: _status trusted: _trusted deleted: _deleted + loading: _loading } } } } -} \ No newline at end of file +} diff --git a/qml/widgets/ContactRow.qml b/qml/widgets/ContactRow.qml index 37943bc9..d19d4a30 100644 --- a/qml/widgets/ContactRow.qml +++ b/qml/widgets/ContactRow.qml @@ -4,6 +4,10 @@ import QtQuick.Controls 2.4 import QtQuick.Controls.Material 2.0 import QtQuick.Layouts 1.3 import CustomQmlTypes 1.0 +import "../styles" +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY anchors.left: parent.left @@ -20,6 +24,7 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY property bool isHover property bool trusted property bool deleted + property bool loading property alias status: imgProfile.status property string server property bool background: true @@ -44,7 +49,7 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY rightPadding: 10 //wrapMode: Text.WordWrap anchors.left: imgProfile.right - anchors.right: rectUnread.left + anchors.right: loadingProgress.left anchors.verticalCenter: parent.verticalCenter font.pixelSize: 16 * gcd.themeScale font.italic: !trusted @@ -80,6 +85,31 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY font: lblUnread.font } } + + ProgressBar { // LOADING ? + id: loadingProgress + property bool running + running: loading + + anchors.right: rectUnread.left + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: 1 * gcd.themeScale + anchors.rightMargin: 1 * gcd.themeScale + + + height: cn.height/2 + width: 100 * gcd.themeScale + + + + indeterminate: true + visible: loading + + style: ProgressBarStyle { + progress: CwtchProgress { running: loadingProgress.running} + } + } + } MouseArea { // ONCLICK: LOAD CONVERSATION WITH THIS CONTACT @@ -112,7 +142,7 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY isActive = false } - onUpdateContact: function(_handle, _displayName, _image, _server, _badge, _status, _trusted) { + onUpdateContact: function(_handle, _displayName, _image, _server, _badge, _status, _trusted, _loading) { if (handle == _handle) { displayName = _displayName image = _image @@ -120,7 +150,17 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY badge = _badge status = _status trusted = _trusted + loading = _loading + + if (loading == true) { + loadingProgress.visible = true + loadingProgress.running = true + } else { + loadingProgress.visible = false + loadingProgress.running = false + } + } } } -} \ No newline at end of file +} diff --git a/qml/widgets/MyProfile.qml b/qml/widgets/MyProfile.qml index 6321f58d..0bdccec4 100644 --- a/qml/widgets/MyProfile.qml +++ b/qml/widgets/MyProfile.qml @@ -230,6 +230,7 @@ ColumnLayout { onion = _onion image = _image parentStack.currentIndex = 1 + splashPane.running = false } onTorStatus: function(code, str) {