From 70e770103ee8d1582998726193f45c0e1cd66901 Mon Sep 17 00:00:00 2001 From: Sale Djenic Date: Thu, 5 May 2022 12:28:54 +0200 Subject: [PATCH] feat(@desktop/profile): add ephemeral notifications - ephemeral notifications implemented as toast messages - old notifications added aligned with new toast messages Fixes #5629 --- src/app/modules/main/chat_section/module.nim | 2 + src/app/modules/main/controller.nim | 4 + .../main/ephemeral_notification_item.nim | 57 +++++++++++ .../main/ephemeral_notification_model.nim | 95 +++++++++++++++++++ src/app/modules/main/io_interface.nim | 11 +++ src/app/modules/main/module.nim | 31 +++++- src/app/modules/main/view.nim | 34 +++++-- ui/app/AppLayouts/Browser/BrowserLayout.qml | 14 +-- .../Chat/views/ContactsColumnView.qml | 42 ++++---- ui/app/AppLayouts/Profile/views/EnsView.qml | 69 ++++++++------ ui/app/mainui/AppMain.qml | 39 ++++++-- ui/imports/shared/popups/SendModal.qml | 14 +-- .../shared/popups/SignTransactionModal.qml | 14 +-- ui/imports/shared/popups/qmldir | 1 - ui/imports/utils/Constants.qml | 5 + ui/imports/utils/Global.qml | 2 +- 16 files changed, 342 insertions(+), 92 deletions(-) create mode 100644 src/app/modules/main/ephemeral_notification_item.nim create mode 100644 src/app/modules/main/ephemeral_notification_model.nim diff --git a/src/app/modules/main/chat_section/module.nim b/src/app/modules/main/chat_section/module.nim index 6e584108a9..400dbed560 100644 --- a/src/app/modules/main/chat_section/module.nim +++ b/src/app/modules/main/chat_section/module.nim @@ -620,6 +620,8 @@ method onContactUnblocked*(self: Module, publicKey: string) = self.view.chatsModel().blockUnblockItemOrSubItemById(publicKey, blocked=false) method onContactDetailsUpdated*(self: Module, publicKey: string) = + if(self.controller.isCommunity()): + return let contactDetails = self.controller.getContactDetails(publicKey) if (contactDetails.details.isContactRequestReceived() and not contactDetails.details.isContactRequestSent() and diff --git a/src/app/modules/main/controller.nim b/src/app/modules/main/controller.nim index 5d04919ffa..62f62fd326 100644 --- a/src/app/modules/main/controller.nim +++ b/src/app/modules/main/controller.nim @@ -188,6 +188,10 @@ proc init*(self: Controller) = var args = ClickedNotificationArgs(e) self.delegate.osNotificationClicked(args.details) + self.events.on(SIGNAL_DISPLAY_APP_NOTIFICATION) do(e: Args): + var args = NotificationArgs(e) + self.delegate.displayEphemeralNotification(args.title, args.message, args.details) + self.events.on(SIGNAL_NEW_REQUEST_TO_JOIN_COMMUNITY) do(e: Args): var args = CommunityRequestArgs(e) self.delegate.newCommunityMembershipRequestReceived(args.communityRequest) diff --git a/src/app/modules/main/ephemeral_notification_item.nim b/src/app/modules/main/ephemeral_notification_item.nim new file mode 100644 index 0000000000..31768126d9 --- /dev/null +++ b/src/app/modules/main/ephemeral_notification_item.nim @@ -0,0 +1,57 @@ +type + EphemeralNotificationType* {.pure.} = enum + Default = 0 + Success + +type + Item* = object + id: int64 + title: string + durationInMs: int + subTitle: string + icon: string + loading: bool + ephNotifType: EphemeralNotificationType + url: string + +proc initItem*(id: int64, + title: string, + durationInMs = 0, + subTitle = "", + icon = "", + loading = false, + ephNotifType = EphemeralNotificationType.Default, + url = ""): Item = + result = Item() + result.id = id + result.durationInMs = durationInMs + result.title = title + result.subTitle = subTitle + result.icon = icon + result.loading = loading + result.ephNotifType = ephNotifType + result.url = url + +proc id*(self: Item): int64 = + self.id + +proc title*(self: Item): string = + self.title + +proc durationInMs*(self: Item): int = + self.durationInMs + +proc subTitle*(self: Item): string = + self.subTitle + +proc icon*(self: Item): string = + self.icon + +proc loading*(self: Item): bool = + self.loading + +proc ephNotifType*(self: Item): EphemeralNotificationType = + self.ephNotifType + +proc url*(self: Item): string = + self.url diff --git a/src/app/modules/main/ephemeral_notification_model.nim b/src/app/modules/main/ephemeral_notification_model.nim new file mode 100644 index 0000000000..b6d5ef3854 --- /dev/null +++ b/src/app/modules/main/ephemeral_notification_model.nim @@ -0,0 +1,95 @@ +import NimQml, Tables +import ephemeral_notification_item + +type + ModelRole {.pure.} = enum + Id = UserRole + 1 + DurationInMs + Title + SubTitle + Icon + Loading + EphNotifType + Url + +QtObject: + type Model* = ref object of QAbstractListModel + items*: seq[Item] + + proc setup(self: Model) = + self.QAbstractListModel.setup + + proc delete(self: Model) = + self.items = @[] + self.QAbstractListModel.delete + + proc newModel*(): Model = + new(result, delete) + result.setup + + method rowCount(self: Model, index: QModelIndex = nil): int = + return self.items.len + + method roleNames(self: Model): Table[int, string] = + { + ModelRole.Id.int:"id", + ModelRole.DurationInMs.int:"durationInMs", + ModelRole.Title.int:"title", + ModelRole.SubTitle.int:"subTitle", + ModelRole.Icon.int:"icon", + ModelRole.Loading.int:"loading", + ModelRole.EphNotifType.int:"ephNotifType", + ModelRole.Url.int:"url" + }.toTable + + method data(self: Model, index: QModelIndex, role: int): QVariant = + if not index.isValid: + return + if index.row < 0 or index.row >= self.items.len: + return + let item = self.items[index.row] + let enumRole = role.ModelRole + + case enumRole: + of ModelRole.Id: + result = newQVariant(item.id) + of ModelRole.DurationInMs: + result = newQVariant(item.durationInMs) + of ModelRole.Title: + result = newQVariant(item.title) + of ModelRole.SubTitle: + result = newQVariant(item.subTitle) + of ModelRole.Icon: + result = newQVariant(item.icon) + of ModelRole.Loading: + result = newQVariant(item.loading) + of ModelRole.EphNotifType: + result = newQVariant(item.ephNotifType.int) + of ModelRole.Url: + result = newQVariant(item.url) + + proc findIndexById(self: Model, id: int64): int = + for i in 0 ..< self.items.len: + if(self.items[i].id == id): + return i + return -1 + + proc addItem*(self: Model, item: Item) = + let parentModelIndex = newQModelIndex() + defer: parentModelIndex.delete + + self.beginInsertRows(parentModelIndex, self.items.len, self.items.len) + self.items.add(item) + self.endInsertRows() + + proc removeItemWithId*(self: Model, id: int64) = + let ind = self.findIndexById(id) + if(ind == -1): + return + + let parentModelIndex = newQModelIndex() + defer: parentModelIndex.delete + + self.beginRemoveRows(parentModelIndex, ind, ind) + self.items.delete(ind) + self.endRemoveRows() \ No newline at end of file diff --git a/src/app/modules/main/io_interface.nim b/src/app/modules/main/io_interface.nim index d54596ee30..913e34b2e6 100644 --- a/src/app/modules/main/io_interface.nim +++ b/src/app/modules/main/io_interface.nim @@ -128,6 +128,17 @@ method mnemonicBackedUp*(self: AccessInterface) {.base.} = method osNotificationClicked*(self: AccessInterface, details: NotificationDetails) {.base.} = raise newException(ValueError, "No implementation available") +method displayEphemeralNotification*(self: AccessInterface, title: string, subTitle: string, details: NotificationDetails) + {.base.} = + raise newException(ValueError, "No implementation available") + +method displayEphemeralNotification*(self: AccessInterface, title: string, subTitle: string, icon: string, loading: bool, + ephNotifType: int, url: string) {.base.} = + raise newException(ValueError, "No implementation available") + +method removeEphemeralNotification*(self: AccessInterface, id: int64) {.base.} = + raise newException(ValueError, "No implementation available") + method newCommunityMembershipRequestReceived*(self: AccessInterface, membershipRequest: CommunityMembershipRequestDto) {.base.} = raise newException(ValueError, "No implementation available") diff --git a/src/app/modules/main/module.nim b/src/app/modules/main/module.nim index 664722ddbd..1bfe133d44 100644 --- a/src/app/modules/main/module.nim +++ b/src/app/modules/main/module.nim @@ -1,6 +1,7 @@ -import NimQml, tables, json, sugar, sequtils, strformat, marshal +import NimQml, tables, json, sugar, sequtils, strformat, marshal, times import io_interface, view, controller, chat_search_item, chat_search_model +import ephemeral_notification_item, ephemeral_notification_model import ./communities/models/[pending_request_item, pending_request_model] import ../shared_models/[user_item, user_model, section_item, section_model, active_section] import ../../global/app_sections_config as conf @@ -57,6 +58,7 @@ import ../../core/eventemitter export io_interface const COMMUNITY_PERMISSION_ACCESS_ON_REQUEST = 3 +const TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS = 5000 # 5 seconds type Module*[T: io_interface.DelegateInterface] = ref object of io_interface.AccessInterface @@ -697,3 +699,30 @@ method newCommunityMembershipRequestReceived*[T](self: Module[T], membershipRequ method meMentionedCountChanged*[T](self: Module[T], allMentions: int) = singletonInstance.globalEvents.meMentionedIconBadgeNotification(allMentions) + +method displayEphemeralNotification*[T](self: Module[T], title: string, subTitle: string, icon: string, loading: bool, + ephNotifType: int, url: string) = + let now = getTime() + let id = now.toUnix * 1000000000 + now.nanosecond + var finalEphNotifType = EphemeralNotificationType.Default + if(ephNotifType == EphemeralNotificationType.Success.int): + finalEphNotifType = EphemeralNotificationType.Success + let item = ephemeral_notification_item.initItem(id, title, TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS, subTitle, icon, + loading, finalEphNotifType, url) + self.view.ephemeralNotificationModel().addItem(item) + +method displayEphemeralNotification*[T](self: Module[T], title: string, subTitle: string, details: NotificationDetails) = + if(details.notificationType == NotificationType.NewMessage or + details.notificationType == NotificationType.NewMessageWithPersonalMention or + details.notificationType == NotificationType.NewMessageWithGlobalMention): + self.displayEphemeralNotification(title, subTitle, "", false, EphemeralNotificationType.Default.int, "") + + elif(details.notificationType == NotificationType.NewContactRequest or + details.notificationType == NotificationType.IdentityVerificationRequest): + self.displayEphemeralNotification(title, subTitle, "contact", false, EphemeralNotificationType.Default.int, "") + + elif(details.notificationType == NotificationType.AcceptedContactRequest): + self.displayEphemeralNotification(title, subTitle, "checkmark-circle", false, EphemeralNotificationType.Success.int, "") + +method removeEphemeralNotification*[T](self: Module[T], id: int64) = + self.view.ephemeralNotificationModel().removeItemWithId(id) \ No newline at end of file diff --git a/src/app/modules/main/view.nim b/src/app/modules/main/view.nim index 41b67d41fb..ed7389038d 100644 --- a/src/app/modules/main/view.nim +++ b/src/app/modules/main/view.nim @@ -1,9 +1,10 @@ -import NimQml +import NimQml, strutils import ../shared_models/section_model import ../shared_models/section_item import ../shared_models/active_section import io_interface import chat_search_model +import ephemeral_notification_model QtObject: type @@ -15,6 +16,8 @@ QtObject: activeSectionVariant: QVariant chatSearchModel: chat_search_model.Model chatSearchModelVariant: QVariant + ephemeralNotificationModel: ephemeralNotification_model.Model + ephemeralNotificationModelVariant: QVariant tmpCommunityId: string # shouldn't be used anywhere except in prepareCommunitySectionModuleForCommunityId/getCommunitySectionModule procs proc activeSectionChanged*(self:View) {.signal.} @@ -26,6 +29,8 @@ QtObject: self.activeSectionVariant.delete self.chatSearchModel.delete self.chatSearchModelVariant.delete + self.ephemeralNotificationModel.delete + self.ephemeralNotificationModelVariant.delete self.QObject.delete proc newView*(delegate: io_interface.AccessInterface): View = @@ -38,6 +43,8 @@ QtObject: result.activeSectionVariant = newQVariant(result.activeSection) result.chatSearchModel = chat_search_model.newModel() result.chatSearchModelVariant = newQVariant(result.chatSearchModel) + result.ephemeralNotificationModel = ephemeralNotification_model.newModel() + result.ephemeralNotificationModelVariant = newQVariant(result.ephemeralNotificationModel) signalConnect(result.model, "notificationsCountChanged()", result, "onNotificationsCountChanged()", 2) @@ -66,21 +73,36 @@ QtObject: proc chatSearchModel*(self: View): chat_search_model.Model = return self.chatSearchModel - proc chatSearchModelChanged*(self: View) {.signal.} - - proc getChatSearchModel(self: View): QVariant {.slot.} = - return self.chatSearchModelVariant - proc rebuildChatSearchModel*(self: View) {.slot.} = self.delegate.rebuildChatSearchModel() proc onNotificationsCountChanged*(self: View) {.slot.} = self.delegate.meMentionedCountChanged(self.model.allMentionsCount()) + proc chatSearchModelChanged*(self: View) {.signal.} + proc getChatSearchModel(self: View): QVariant {.slot.} = + return self.chatSearchModelVariant QtProperty[QVariant] chatSearchModel: read = getChatSearchModel notify = chatSearchModelChanged + proc ephemeralNotificationModel*(self: View): ephemeralNotification_model.Model = + return self.ephemeralNotificationModel + + proc ephemeralNotificationModelChanged*(self: View) {.signal.} + proc getEphemeralNotificationModel(self: View): QVariant {.slot.} = + return self.ephemeralNotificationModelVariant + QtProperty[QVariant] ephemeralNotificationModel: + read = getEphemeralNotificationModel + notify = ephemeralNotificationModelChanged + + proc displayEphemeralNotification*(self: View, title: string, subTitle: string, icon: string, loading: bool, + ephNotifType: int, url: string) {.slot.} = + self.delegate.displayEphemeralNotification(title, subTitle, icon, loading, ephNotifType, url) + + proc removeEphemeralNotification*(self: View, id: string) {.slot.} = + self.delegate.removeEphemeralNotification(id.parseInt) + proc openStoreToKeychainPopup*(self: View) {.signal.} proc offerToStorePassword*(self: View) = diff --git a/ui/app/AppLayouts/Browser/BrowserLayout.qml b/ui/app/AppLayouts/Browser/BrowserLayout.qml index 23c6099c6b..6f0b4c240f 100644 --- a/ui/app/AppLayouts/Browser/BrowserLayout.qml +++ b/ui/app/AppLayouts/Browser/BrowserLayout.qml @@ -194,13 +194,13 @@ Rectangle { } showToastMessage: function(result) { // TODO: WIP under PR https://github.com/status-im/status-desktop/pull/4274 - //% "Transaction pending..." - toastMessage.title = qsTrId("ens-transaction-pending") - toastMessage.source = Style.svg("loading") - toastMessage.iconColor = Style.current.primary - toastMessage.iconRotates = true - toastMessage.link = `${WalletStore.getEtherscanLink()}/${result}` - toastMessage.open() + let url = `${WalletStore.getEtherscanLink()}/${result}`; + Global.displayToastMessage(qsTr("Transaction pending..."), + "", + "", + true, + Constants.ephemeralNotificationType.normal, + url); } } diff --git a/ui/app/AppLayouts/Chat/views/ContactsColumnView.qml b/ui/app/AppLayouts/Chat/views/ContactsColumnView.qml index 1fcffc787f..d77044a75e 100644 --- a/ui/app/AppLayouts/Chat/views/ContactsColumnView.qml +++ b/ui/app/AppLayouts/Chat/views/ContactsColumnView.qml @@ -362,43 +362,37 @@ Item { Connections { target: root.store.communitiesModuleInst onImportingCommunityStateChanged: { - if (state !== Constants.communityImported && - state !== Constants.communityImportingInProgress && - state !== Constants.communityImportingError) - { - return - } - - Global.toastMessage.close() + let title = "" + let loading = false if (state === Constants.communityImported) { //% "Community imported" - Global.toastMessage.title = qsTrId("community-imported") - Global.toastMessage.source = "" - Global.toastMessage.iconRotates = false - Global.toastMessage.dissapearInMs = 4000 + title = qsTrId("community-imported") } else if (state === Constants.communityImportingInProgress) { //% "Importing community is in progress" - Global.toastMessage.title = qsTrId("importing-community-is-in-progress") - Global.toastMessage.source = Style.svg("loading") - Global.toastMessage.iconRotates = true - Global.toastMessage.dissapearInMs = -1 + title = qsTrId("importing-community-is-in-progress") + loading = true } else if (state === Constants.communityImportingError) { - Global.toastMessage.title = errorMsg - Global.toastMessage.source = "" - Global.toastMessage.iconRotates = false - Global.toastMessage.dissapearInMs = 4000 + title = errorMsg } - Global.toastMessage.displayCloseButton = false - Global.toastMessage.displayLink = false - Global.toastMessage.iconColor = Style.current.primary - Global.toastMessage.open() + if(title == "") + { + console.error("unknown state while importing community: ", state) + return + } + + Global.displayToastMessage(title, + "", + "", + loading, + Constants.ephemeralNotificationType.normal, + "") } } diff --git a/ui/app/AppLayouts/Profile/views/EnsView.qml b/ui/app/AppLayouts/Profile/views/EnsView.qml index 357ad9056a..d937e76c28 100644 --- a/ui/app/AppLayouts/Profile/views/EnsView.qml +++ b/ui/app/AppLayouts/Profile/views/EnsView.qml @@ -323,43 +323,52 @@ Item { Connections { target: ensView.ensUsernamesStore.ensUsernamesModule onTransactionWasSent: { - //% "Transaction pending..." - Global.toastMessage.title = qsTrId("ens-transaction-pending") - Global.toastMessage.source = Style.svg("loading") - Global.toastMessage.iconColor = Style.current.primary - Global.toastMessage.iconRotates = true - Global.toastMessage.link = `${ensView.ensUsernamesStore.getEtherscanLink()}/${txResult}` - Global.toastMessage.open() + let url = `${ensView.ensUsernamesStore.getEtherscanLink()}/${txResult}`; + Global.displayToastMessage(qsTr("Transaction pending..."), + "", + "", + true, + Constants.ephemeralNotificationType.normal, + url); } onTransactionCompleted: { + let title = "" switch(trxType){ - case "RegisterENS": - Global.toastMessage.title = !success ? - //% "ENS Registration failed" - qsTrId("ens-registration-failed") - : - //% "ENS Registration completed" - qsTrId("ens-registration-completed"); - break; - case "SetPubKey": - Global.toastMessage.title = !success ? - //% "Updating ENS pubkey failed" - qsTrId("updating-ens-pubkey-failed") - : - //% "Updating ENS pubkey completed" - qsTrId("updating-ens-pubkey-completed"); - break; + case "RegisterENS": + title = !success ? + //% "ENS Registration failed" + qsTrId("ens-registration-failed") + : + //% "ENS Registration completed" + qsTrId("ens-registration-completed"); + break; + case "SetPubKey": + title = !success ? + //% "Updating ENS pubkey failed" + qsTrId("updating-ens-pubkey-failed") + : + //% "Updating ENS pubkey completed" + qsTrId("updating-ens-pubkey-completed"); + break; + default: + console.error("unknown transaction type: ", trxType); + return } + let icon = "block-icon"; + let ephType = Constants.ephemeralNotificationType.normal; if (success) { - Global.toastMessage.source = Style.svg("check-circle") - Global.toastMessage.iconColor = Style.current.success - } else { - Global.toastMessage.source = Style.svg("block-icon") - Global.toastMessage.iconColor = Style.current.danger + icon = "check-circle"; + ephType = Constants.ephemeralNotificationType.success; } - Global.toastMessage.link = `${ensView.ensUsernamesStore.getEtherscanLink()}/${txHash}` - Global.toastMessage.open() + + let url = `${ensView.ensUsernamesStore.getEtherscanLink()}/${txHash}`; + Global.displayToastMessage(qsTr("Transaction pending..."), + "", + icon, + false, + ephType, + url) } } } diff --git a/ui/app/mainui/AppMain.qml b/ui/app/mainui/AppMain.qml index f6c5caaa9c..29fd1e8fcc 100644 --- a/ui/app/mainui/AppMain.qml +++ b/ui/app/mainui/AppMain.qml @@ -97,6 +97,9 @@ Item { var popup = backupSeedModalComponent.createObject(appMain) popup.open() } + onDisplayToastMessage: { + appMain.rootStore.mainModuleInst.displayEphemeralNotification(title, subTitle, icon, loading, ephNotifType, url); + } } function changeAppSectionBySectionId(sectionId) { @@ -742,14 +745,6 @@ Item { } } - ToastMessage { - id: toastMessage - Component.onCompleted: { - Global.toastMessage = this; - } - } - - DropArea { id: dragTarget @@ -949,6 +944,34 @@ Item { } } + ListView { + id: toastArea + anchors.top: parent.top + anchors.topMargin: 60 + anchors.right: parent.right + anchors.rightMargin: 8 + anchors.bottom: parent.bottom + anchors.bottomMargin: 60 + spacing: 8 + verticalLayoutDirection: ListView.BottomToTop + model: appMain.rootStore.mainModuleInst.ephemeralNotificationModel + delegate: StatusToastMessage { + primaryText: model.title + secondaryText: model.subTitle + icon.name: model.icon + loading: model.loading + type: model.ephNotifType + linkUrl: model.url + duration: model.durationInMs + onLinkActivated: { + Qt.openUrlExternally(link); + } + onClose: { + appMain.rootStore.mainModuleInst.removeEphemeralNotification(model.id) + } + } + } + Component.onCompleted: { Global.appMain = this; const whitelist = appMain.rootStore.messagingStore.getLinkPreviewWhitelist() diff --git a/ui/imports/shared/popups/SendModal.qml b/ui/imports/shared/popups/SendModal.qml index 1c461e11bf..51d3f81ad7 100644 --- a/ui/imports/shared/popups/SendModal.qml +++ b/ui/imports/shared/popups/SendModal.qml @@ -275,13 +275,13 @@ StatusModal { return sendingError.open() } - // % "Transaction pending..." - Global.toastMessage.title = qsTrId("ens-transaction-pending") - Global.toastMessage.source = Style.svg("loading") - Global.toastMessage.iconColor = Style.current.primary - Global.toastMessage.iconRotates = true - Global.toastMessage.link = `${popup.store.getEtherscanLink()}/${response.result}` - Global.toastMessage.open() + let url = `${popup.store.getEtherscanLink()}/${response.result}` + Global.displayToastMessage(qsTr("Transaction pending..."), + "", + "", + true, + Constants.ephemeralNotificationType.normal, + url) popup.close() } catch (e) { console.error('Error parsing the response', e) diff --git a/ui/imports/shared/popups/SignTransactionModal.qml b/ui/imports/shared/popups/SignTransactionModal.qml index 919069769b..c5e22d983f 100644 --- a/ui/imports/shared/popups/SignTransactionModal.qml +++ b/ui/imports/shared/popups/SignTransactionModal.qml @@ -363,14 +363,14 @@ StatusModal { if(isARequest) root.store.acceptRequestTransaction(transactionId, msgId, root.store.getPubkey() + transactionId.substr(2)) - //% "Transaction pending..." - Global.toastMessage.title = qsTrId("ens-transaction-pending") - Global.toastMessage.source = Style.svg("loading") - Global.toastMessage.iconColor = Style.current.primary - Global.toastMessage.iconRotates = true // Refactor this - // Global.toastMessage.link = `${walletModel.utilsView.etherscanLink}/${response.result}` - Global.toastMessage.open() + let url = "" //`${walletModel.utilsView.etherscanLink}/${response.result}` + Global.displayToastMessage(qsTr("Transaction pending..."), + "", + "", + true, + Constants.ephemeralNotificationType.normal, + url) root.close() } catch (e) { diff --git a/ui/imports/shared/popups/qmldir b/ui/imports/shared/popups/qmldir index 4d406fd63f..b1d55aef64 100644 --- a/ui/imports/shared/popups/qmldir +++ b/ui/imports/shared/popups/qmldir @@ -8,7 +8,6 @@ InviteFriendsPopup 1.0 InviteFriendsPopup.qml ModalPopup 1.0 ModalPopup.qml PopupMenu 1.0 PopupMenu.qml SendModal 1.0 SendModal.qml -ToastMessage 1.0 ToastMessage.qml TransactionModal 1.0 TransactionModal.qml TransactionSettingsConfirmationPopup 1.0 TransactionSettingsConfirmationPopup.qml UnblockContactConfirmationDialog 1.0 UnblockContactConfirmationDialog.qml diff --git a/ui/imports/utils/Constants.qml b/ui/imports/utils/Constants.qml index 0c46243308..6e7a533aef 100644 --- a/ui/imports/utils/Constants.qml +++ b/ui/imports/utils/Constants.qml @@ -180,6 +180,11 @@ QtObject { } } + readonly property QtObject ephemeralNotificationType: QtObject { + readonly property int normal: 0 + readonly property int success: 1 + } + readonly property int communityImported: 0 readonly property int communityImportingInProgress: 1 readonly property int communityImportingError: 2 diff --git a/ui/imports/utils/Global.qml b/ui/imports/utils/Global.qml index d629c5e4cf..0a928d374e 100644 --- a/ui/imports/utils/Global.qml +++ b/ui/imports/utils/Global.qml @@ -14,7 +14,6 @@ QtObject { property var mainModuleInst property var privacyModuleInst - property var toastMessage property bool profilePopupOpened: false property string currentNetworkId: "" property bool networkGuarded: root.currentNetworkId === Constants.networkMainnet || @@ -29,6 +28,7 @@ QtObject { signal openProfilePopupRequested(string publicKey, var parentPopup, bool openNicknamePopup) signal openChangeProfilePicPopup() + signal displayToastMessage(string title, string subTitle, string icon, bool loading, int ephNotifType, string url) function openProfilePopup(publicKey, parentPopup, openNicknamePopup){ openProfilePopupRequested(publicKey, parentPopup, openNicknamePopup);