feature(@desktop/communities): add loading state when import community

Toast message is added when user access an existing community using community's private key. Toast
message with message that importing community is in progress is displayed while community is being
imported and once it is imported toast is closed and new one, which will be closed in 4 seconds,
with message that community is imported is displayed.

Fixes: #2467
This commit is contained in:
Sale Djenic 2021-07-16 07:37:07 +02:00 committed by Iuri Matias
parent 9a348e1836
commit e9585e6209
5 changed files with 161 additions and 67 deletions

View File

@ -12,6 +12,12 @@ import ../../../status/types
logScope:
topics = "communities-view"
type
CommunityImportState {.pure.} = enum
Imported,
InProgress,
Error
QtObject:
type CommunitiesView* = ref object of QObject
status: Status
@ -20,6 +26,8 @@ QtObject:
communityList*: CommunityList
joinedCommunityList*: CommunityList
myCommunityRequests*: seq[CommunityMembershipRequest]
importingCommunityState: CommunityImportState
communityImportingProcessId: string
proc setup(self: CommunitiesView) =
self.QObject.setup
@ -33,6 +41,7 @@ QtObject:
proc newCommunitiesView*(status: Status): CommunitiesView =
new(result, delete)
result.importingCommunityState = CommunityImportState.Imported
result.status = status
result.activeCommunity = newCommunityItemView(status)
result.observedCommunity = newCommunityItemView(status)
@ -40,6 +49,16 @@ QtObject:
result.joinedCommunityList = newCommunityList(status)
result.setup
proc importingCommunityStateChanged*(self: CommunitiesView, state: int, communityImportingProcessId: string) {.signal.}
proc setImportCommunityState(self: CommunitiesView, state: CommunityImportState, communityImportingProcessId: string) =
if (self.importingCommunityState == state):
return
self.communityImportingProcessId = communityImportingProcessId
self.importingCommunityState = state
self.importingCommunityStateChanged(state.int, communityImportingProcessId)
proc calculateUnreadMessages*(self: CommunitiesView, community: var Community) =
var unreadTotal = 0
for chatItem in community.chats:
@ -230,6 +249,8 @@ QtObject:
# @cammellos mentioned this would likely changed in Communities Phase 3, so
# no need to polish now.
self.setImportCommunityState(CommunityImportState.Imported, self.communityImportingProcessId)
proc isCommunityRequestPending*(self: CommunitiesView, communityId: string): bool {.slot.} =
for communityRequest in self.myCommunityRequests:
if (communityRequest.communityId == communityId):
@ -369,10 +390,22 @@ QtObject:
error "Error exporting the community", msg = e.msg
result = fmt"Error exporting the community: {e.msg}"
proc importCommunity*(self: CommunitiesView, communityKey: string): string {.slot.} =
proc importCommunity*(self: CommunitiesView, communityKey: string, communityImportingProcessId: string): string {.slot.} =
try:
discard self.status.chat.importCommunity(communityKey)
self.setImportCommunityState(CommunityImportState.InProgress, communityImportingProcessId)
let response = self.status.chat.importCommunity(communityKey)
let jsonNode = response.parseJSON()
if (jsonNode.contains("error")):
if (jsonNode["error"].contains("message")):
let msg = jsonNode["error"]["message"].getStr()
result = fmt"Error importing the community: {msg}"
else:
result = fmt"Error importing the community: unknown error"
self.setImportCommunityState(CommunityImportState.Error, communityImportingProcessId)
except Exception as e:
self.setImportCommunityState(CommunityImportState.Error, communityImportingProcessId)
error "Error importing the community", msg = e.msg
result = fmt"Error importing the community: {e.msg}"

View File

@ -65,7 +65,7 @@ ModalPopup {
communityKey = "0x" + communityKey
}
const error = chatsModel.communities.importCommunity(communityKey)
const error = chatsModel.communities.importCommunity(communityKey, Utils.uuid())
if (error) {
creatingError.text = error

View File

@ -239,10 +239,50 @@ Item {
}
}
}
}
/*##^##
Designer {
D{i:0;autoSize:true;formeditorColor:"#ffffff";height:480;width:640}
Connections {
target: chatsModel.communities
onImportingCommunityStateChanged: {
if (state !== Constants.communityImported &&
state !== Constants.communityImportingInProgress &&
state !== Constants.communityImportingError)
{
return
}
if (state === Constants.communityImported)
{
if (toastMessage.uuid !== communityImportingProcessId)
return
toastMessage.close()
toastMessage.title = qsTr("Community imported")
toastMessage.source = ""
toastMessage.iconRotates = false
toastMessage.dissapearInMs = 4000
}
else if (state === Constants.communityImportingInProgress)
{
toastMessage.uuid = communityImportingProcessId
toastMessage.title = qsTr("Importing community is in progress")
toastMessage.source = "../../img/loading.svg"
toastMessage.iconRotates = true
toastMessage.dissapearInMs = -1
}
else if (state === Constants.communityImportingError)
{
if (toastMessage.uuid !== communityImportingProcessId)
return
toastMessage.close()
return
}
toastMessage.displayCloseButton = false
toastMessage.displayLink = false
toastMessage.iconColor = Style.current.primary
toastMessage.open()
}
}
}
##^##*/

View File

@ -3,6 +3,10 @@ pragma Singleton
import QtQuick 2.13
QtObject {
readonly property int communityImported: 0
readonly property int communityImportingInProgress: 1
readonly property int communityImportingError: 2
readonly property int chatTypeOneToOne: 1
readonly property int chatTypePublic: 2
readonly property int chatTypePrivateGroupChat: 3

View File

@ -5,34 +5,52 @@ import "../imports"
import "."
Popup {
property url source: "../app/img/check-circle.svg"
property color iconColor: Style.current.primary
property bool iconRotates: false
property string title: "Transaction pending..."
//% "View on Etherscan"
readonly property string defaultLinkText: qsTrId("view-on-etherscan")
property string link: "https://etherscan.io/"
property string linkText: defaultLinkText
id: root
closePolicy: Popup.NoAutoClose
height: 68
padding: 0
margins: 0
width: Math.max(Math.max(titleText.width, linkText.width) + toastImage.width + 12 * 4, 343)
width: Math.max(Math.max(titleText.width, linkStyledText.width)
+ (toastImage.visible? toastImage.width + rowId.spacing : 0)
+ rowId.leftPadding + rowId.rightPadding,
343)
x: parent.width - width - Style.current.bigPadding
y: parent.height - height - Style.current.bigPadding
//% "View on Etherscan"
readonly property string defaultLinkText: qsTrId("view-on-etherscan")
property string uuid: "" // set this if you want to distinct among multiple toasts
property url source: "../app/img/check-circle.svg"
property color iconColor: Style.current.primary
property bool iconRotates: false
property string title: "Transaction pending..."
property string link: "https://etherscan.io/"
property string linkText: defaultLinkText
property int dissapearInMs: 4000 /* setting this to -1 makes caller responsible to close it */
property bool displayCloseButton: true
property bool displayLink: true
onOpened: {
if(dissapearInMs == -1)
return
timer.setTimeout(function() {
root.close()
}, 4000);
}, dissapearInMs);
}
onClosed: {
// Reset props
source = "../app/img/check-circle.svg"
iconColor = Style.current.primary
iconRotates = false
root.linkText = defaultLinkText
title = "Transaction pending..."
link = "https://etherscan.io/"
linkText = defaultLinkText
dissapearInMs = 4000
displayCloseButton = true
displayLink = true
}
Timer {
@ -60,54 +78,58 @@ Popup {
}
}
RoundedIcon {
id: toastImage
width: 32
height: 32
iconHeight: 20
iconWidth: 20
color: Utils.setColorAlpha(root.iconColor, 0.1)
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
source: root.source
anchors.leftMargin: 12
iconColor: root.iconColor
rotates: root.iconRotates
}
Row {
id: rowId
anchors.fill: parent
leftPadding: 12
rightPadding: 12
topPadding: Style.current.padding
bottomPadding: Style.current.padding
spacing: 12
StyledText {
id: titleText
text: root.title
anchors.left: toastImage.right
anchors.top: parent.top
font.pixelSize: 13
font.weight: Font.Medium
anchors.topMargin: Style.current.padding
anchors.leftMargin: 12
}
RoundedIcon {
id: toastImage
visible: root.source != ""
width: 32
height: 32
iconHeight: 20
iconWidth: 20
color: Utils.setColorAlpha(root.iconColor, 0.1)
anchors.verticalCenter: parent.verticalCenter
source: root.source
iconColor: root.iconColor
rotates: root.iconRotates
}
StyledText {
id: linkText
//% "<a href='%1' style='color:%2;text-decoration:none;'>%3</a>"
text: qsTrId("-a-href---1--style--color--2-text-decoration-none----3--a-")
.arg(Style.current.textColorTertiary)
.arg(root.link)
.arg(root.linkText)
color: Style.current.textColorTertiary
textFormat: Text.RichText
anchors.left: toastImage.right
anchors.top: titleText.bottom
font.pixelSize: 13
font.weight: Font.Medium
anchors.leftMargin: 12
onLinkActivated: {
appMain.openLink(root.link)
root.close()
Column {
anchors.verticalCenter: parent.verticalCenter
StyledText {
id: titleText
text: root.title
font.pixelSize: 13
font.weight: Font.Medium
}
StyledText {
id: linkStyledText
visible: displayLink
text: `<a href='${root.link}' style='color:${Style.current.textColorTertiary};text-decoration:none;'>${root.linkText}</a>`
color: Style.current.textColorTertiary
textFormat: Text.RichText
font.pixelSize: 13
font.weight: Font.Medium
onLinkActivated: {
appMain.openLink(root.link)
root.close()
}
}
}
}
SVGImage {
id: closeImage
visible: displayCloseButton
anchors.right: parent.right
anchors.top: parent.top
source: "../app/img/plusSign.svg"
@ -126,15 +148,10 @@ Popup {
}
}
ColorOverlay {
visible: displayCloseButton
anchors.fill: closeImage
source: closeImage
rotation: 45
color: Style.current.textColor
}
}
/*##^##
Designer {
D{i:0;formeditorColor:"#4c4e50";formeditorZoom:1.5;height:68;width:343}
}
##^##*/