feat(@desktop/profile): add ephemeral notifications

- ephemeral notifications implemented as toast messages
- old notifications added aligned with new toast messages

Fixes #5629
This commit is contained in:
Sale Djenic 2022-05-05 12:28:54 +02:00 committed by saledjenic
parent 242d980377
commit 70e770103e
16 changed files with 342 additions and 92 deletions

View File

@ -620,6 +620,8 @@ method onContactUnblocked*(self: Module, publicKey: string) =
self.view.chatsModel().blockUnblockItemOrSubItemById(publicKey, blocked=false) self.view.chatsModel().blockUnblockItemOrSubItemById(publicKey, blocked=false)
method onContactDetailsUpdated*(self: Module, publicKey: string) = method onContactDetailsUpdated*(self: Module, publicKey: string) =
if(self.controller.isCommunity()):
return
let contactDetails = self.controller.getContactDetails(publicKey) let contactDetails = self.controller.getContactDetails(publicKey)
if (contactDetails.details.isContactRequestReceived() and if (contactDetails.details.isContactRequestReceived() and
not contactDetails.details.isContactRequestSent() and not contactDetails.details.isContactRequestSent() and

View File

@ -188,6 +188,10 @@ proc init*(self: Controller) =
var args = ClickedNotificationArgs(e) var args = ClickedNotificationArgs(e)
self.delegate.osNotificationClicked(args.details) 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): self.events.on(SIGNAL_NEW_REQUEST_TO_JOIN_COMMUNITY) do(e: Args):
var args = CommunityRequestArgs(e) var args = CommunityRequestArgs(e)
self.delegate.newCommunityMembershipRequestReceived(args.communityRequest) self.delegate.newCommunityMembershipRequestReceived(args.communityRequest)

View File

@ -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

View File

@ -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()

View File

@ -128,6 +128,17 @@ method mnemonicBackedUp*(self: AccessInterface) {.base.} =
method osNotificationClicked*(self: AccessInterface, details: NotificationDetails) {.base.} = method osNotificationClicked*(self: AccessInterface, details: NotificationDetails) {.base.} =
raise newException(ValueError, "No implementation available") 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) method newCommunityMembershipRequestReceived*(self: AccessInterface, membershipRequest: CommunityMembershipRequestDto)
{.base.} = {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -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 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 ./communities/models/[pending_request_item, pending_request_model]
import ../shared_models/[user_item, user_model, section_item, section_model, active_section] import ../shared_models/[user_item, user_model, section_item, section_model, active_section]
import ../../global/app_sections_config as conf import ../../global/app_sections_config as conf
@ -57,6 +58,7 @@ import ../../core/eventemitter
export io_interface export io_interface
const COMMUNITY_PERMISSION_ACCESS_ON_REQUEST = 3 const COMMUNITY_PERMISSION_ACCESS_ON_REQUEST = 3
const TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS = 5000 # 5 seconds
type type
Module*[T: io_interface.DelegateInterface] = ref object of io_interface.AccessInterface 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) = method meMentionedCountChanged*[T](self: Module[T], allMentions: int) =
singletonInstance.globalEvents.meMentionedIconBadgeNotification(allMentions) 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)

View File

@ -1,9 +1,10 @@
import NimQml import NimQml, strutils
import ../shared_models/section_model import ../shared_models/section_model
import ../shared_models/section_item import ../shared_models/section_item
import ../shared_models/active_section import ../shared_models/active_section
import io_interface import io_interface
import chat_search_model import chat_search_model
import ephemeral_notification_model
QtObject: QtObject:
type type
@ -15,6 +16,8 @@ QtObject:
activeSectionVariant: QVariant activeSectionVariant: QVariant
chatSearchModel: chat_search_model.Model chatSearchModel: chat_search_model.Model
chatSearchModelVariant: QVariant chatSearchModelVariant: QVariant
ephemeralNotificationModel: ephemeralNotification_model.Model
ephemeralNotificationModelVariant: QVariant
tmpCommunityId: string # shouldn't be used anywhere except in prepareCommunitySectionModuleForCommunityId/getCommunitySectionModule procs tmpCommunityId: string # shouldn't be used anywhere except in prepareCommunitySectionModuleForCommunityId/getCommunitySectionModule procs
proc activeSectionChanged*(self:View) {.signal.} proc activeSectionChanged*(self:View) {.signal.}
@ -26,6 +29,8 @@ QtObject:
self.activeSectionVariant.delete self.activeSectionVariant.delete
self.chatSearchModel.delete self.chatSearchModel.delete
self.chatSearchModelVariant.delete self.chatSearchModelVariant.delete
self.ephemeralNotificationModel.delete
self.ephemeralNotificationModelVariant.delete
self.QObject.delete self.QObject.delete
proc newView*(delegate: io_interface.AccessInterface): View = proc newView*(delegate: io_interface.AccessInterface): View =
@ -38,6 +43,8 @@ QtObject:
result.activeSectionVariant = newQVariant(result.activeSection) result.activeSectionVariant = newQVariant(result.activeSection)
result.chatSearchModel = chat_search_model.newModel() result.chatSearchModel = chat_search_model.newModel()
result.chatSearchModelVariant = newQVariant(result.chatSearchModel) result.chatSearchModelVariant = newQVariant(result.chatSearchModel)
result.ephemeralNotificationModel = ephemeralNotification_model.newModel()
result.ephemeralNotificationModelVariant = newQVariant(result.ephemeralNotificationModel)
signalConnect(result.model, "notificationsCountChanged()", result, signalConnect(result.model, "notificationsCountChanged()", result,
"onNotificationsCountChanged()", 2) "onNotificationsCountChanged()", 2)
@ -66,21 +73,36 @@ QtObject:
proc chatSearchModel*(self: View): chat_search_model.Model = proc chatSearchModel*(self: View): chat_search_model.Model =
return self.chatSearchModel return self.chatSearchModel
proc chatSearchModelChanged*(self: View) {.signal.}
proc getChatSearchModel(self: View): QVariant {.slot.} =
return self.chatSearchModelVariant
proc rebuildChatSearchModel*(self: View) {.slot.} = proc rebuildChatSearchModel*(self: View) {.slot.} =
self.delegate.rebuildChatSearchModel() self.delegate.rebuildChatSearchModel()
proc onNotificationsCountChanged*(self: View) {.slot.} = proc onNotificationsCountChanged*(self: View) {.slot.} =
self.delegate.meMentionedCountChanged(self.model.allMentionsCount()) self.delegate.meMentionedCountChanged(self.model.allMentionsCount())
proc chatSearchModelChanged*(self: View) {.signal.}
proc getChatSearchModel(self: View): QVariant {.slot.} =
return self.chatSearchModelVariant
QtProperty[QVariant] chatSearchModel: QtProperty[QVariant] chatSearchModel:
read = getChatSearchModel read = getChatSearchModel
notify = chatSearchModelChanged 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 openStoreToKeychainPopup*(self: View) {.signal.}
proc offerToStorePassword*(self: View) = proc offerToStorePassword*(self: View) =

View File

@ -194,13 +194,13 @@ Rectangle {
} }
showToastMessage: function(result) { showToastMessage: function(result) {
// TODO: WIP under PR https://github.com/status-im/status-desktop/pull/4274 // TODO: WIP under PR https://github.com/status-im/status-desktop/pull/4274
//% "Transaction pending..." let url = `${WalletStore.getEtherscanLink()}/${result}`;
toastMessage.title = qsTrId("ens-transaction-pending") Global.displayToastMessage(qsTr("Transaction pending..."),
toastMessage.source = Style.svg("loading") "",
toastMessage.iconColor = Style.current.primary "",
toastMessage.iconRotates = true true,
toastMessage.link = `${WalletStore.getEtherscanLink()}/${result}` Constants.ephemeralNotificationType.normal,
toastMessage.open() url);
} }
} }

View File

@ -362,43 +362,37 @@ Item {
Connections { Connections {
target: root.store.communitiesModuleInst target: root.store.communitiesModuleInst
onImportingCommunityStateChanged: { onImportingCommunityStateChanged: {
if (state !== Constants.communityImported && let title = ""
state !== Constants.communityImportingInProgress && let loading = false
state !== Constants.communityImportingError)
{
return
}
Global.toastMessage.close()
if (state === Constants.communityImported) if (state === Constants.communityImported)
{ {
//% "Community imported" //% "Community imported"
Global.toastMessage.title = qsTrId("community-imported") title = qsTrId("community-imported")
Global.toastMessage.source = ""
Global.toastMessage.iconRotates = false
Global.toastMessage.dissapearInMs = 4000
} }
else if (state === Constants.communityImportingInProgress) else if (state === Constants.communityImportingInProgress)
{ {
//% "Importing community is in progress" //% "Importing community is in progress"
Global.toastMessage.title = qsTrId("importing-community-is-in-progress") title = qsTrId("importing-community-is-in-progress")
Global.toastMessage.source = Style.svg("loading") loading = true
Global.toastMessage.iconRotates = true
Global.toastMessage.dissapearInMs = -1
} }
else if (state === Constants.communityImportingError) else if (state === Constants.communityImportingError)
{ {
Global.toastMessage.title = errorMsg title = errorMsg
Global.toastMessage.source = ""
Global.toastMessage.iconRotates = false
Global.toastMessage.dissapearInMs = 4000
} }
Global.toastMessage.displayCloseButton = false if(title == "")
Global.toastMessage.displayLink = false {
Global.toastMessage.iconColor = Style.current.primary console.error("unknown state while importing community: ", state)
Global.toastMessage.open() return
}
Global.displayToastMessage(title,
"",
"",
loading,
Constants.ephemeralNotificationType.normal,
"")
} }
} }

View File

@ -323,43 +323,52 @@ Item {
Connections { Connections {
target: ensView.ensUsernamesStore.ensUsernamesModule target: ensView.ensUsernamesStore.ensUsernamesModule
onTransactionWasSent: { onTransactionWasSent: {
//% "Transaction pending..." let url = `${ensView.ensUsernamesStore.getEtherscanLink()}/${txResult}`;
Global.toastMessage.title = qsTrId("ens-transaction-pending") Global.displayToastMessage(qsTr("Transaction pending..."),
Global.toastMessage.source = Style.svg("loading") "",
Global.toastMessage.iconColor = Style.current.primary "",
Global.toastMessage.iconRotates = true true,
Global.toastMessage.link = `${ensView.ensUsernamesStore.getEtherscanLink()}/${txResult}` Constants.ephemeralNotificationType.normal,
Global.toastMessage.open() url);
} }
onTransactionCompleted: { onTransactionCompleted: {
let title = ""
switch(trxType){ switch(trxType){
case "RegisterENS": case "RegisterENS":
Global.toastMessage.title = !success ? title = !success ?
//% "ENS Registration failed" //% "ENS Registration failed"
qsTrId("ens-registration-failed") qsTrId("ens-registration-failed")
: :
//% "ENS Registration completed" //% "ENS Registration completed"
qsTrId("ens-registration-completed"); qsTrId("ens-registration-completed");
break; break;
case "SetPubKey": case "SetPubKey":
Global.toastMessage.title = !success ? title = !success ?
//% "Updating ENS pubkey failed" //% "Updating ENS pubkey failed"
qsTrId("updating-ens-pubkey-failed") qsTrId("updating-ens-pubkey-failed")
: :
//% "Updating ENS pubkey completed" //% "Updating ENS pubkey completed"
qsTrId("updating-ens-pubkey-completed"); qsTrId("updating-ens-pubkey-completed");
break; break;
default:
console.error("unknown transaction type: ", trxType);
return
} }
let icon = "block-icon";
let ephType = Constants.ephemeralNotificationType.normal;
if (success) { if (success) {
Global.toastMessage.source = Style.svg("check-circle") icon = "check-circle";
Global.toastMessage.iconColor = Style.current.success ephType = Constants.ephemeralNotificationType.success;
} else {
Global.toastMessage.source = Style.svg("block-icon")
Global.toastMessage.iconColor = Style.current.danger
} }
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)
} }
} }
} }

View File

@ -97,6 +97,9 @@ Item {
var popup = backupSeedModalComponent.createObject(appMain) var popup = backupSeedModalComponent.createObject(appMain)
popup.open() popup.open()
} }
onDisplayToastMessage: {
appMain.rootStore.mainModuleInst.displayEphemeralNotification(title, subTitle, icon, loading, ephNotifType, url);
}
} }
function changeAppSectionBySectionId(sectionId) { function changeAppSectionBySectionId(sectionId) {
@ -742,14 +745,6 @@ Item {
} }
} }
ToastMessage {
id: toastMessage
Component.onCompleted: {
Global.toastMessage = this;
}
}
DropArea { DropArea {
id: dragTarget 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: { Component.onCompleted: {
Global.appMain = this; Global.appMain = this;
const whitelist = appMain.rootStore.messagingStore.getLinkPreviewWhitelist() const whitelist = appMain.rootStore.messagingStore.getLinkPreviewWhitelist()

View File

@ -275,13 +275,13 @@ StatusModal {
return sendingError.open() return sendingError.open()
} }
// % "Transaction pending..." let url = `${popup.store.getEtherscanLink()}/${response.result}`
Global.toastMessage.title = qsTrId("ens-transaction-pending") Global.displayToastMessage(qsTr("Transaction pending..."),
Global.toastMessage.source = Style.svg("loading") "",
Global.toastMessage.iconColor = Style.current.primary "",
Global.toastMessage.iconRotates = true true,
Global.toastMessage.link = `${popup.store.getEtherscanLink()}/${response.result}` Constants.ephemeralNotificationType.normal,
Global.toastMessage.open() url)
popup.close() popup.close()
} catch (e) { } catch (e) {
console.error('Error parsing the response', e) console.error('Error parsing the response', e)

View File

@ -363,14 +363,14 @@ StatusModal {
if(isARequest) if(isARequest)
root.store.acceptRequestTransaction(transactionId, msgId, root.store.getPubkey() + transactionId.substr(2)) 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 // Refactor this
// Global.toastMessage.link = `${walletModel.utilsView.etherscanLink}/${response.result}` let url = "" //`${walletModel.utilsView.etherscanLink}/${response.result}`
Global.toastMessage.open() Global.displayToastMessage(qsTr("Transaction pending..."),
"",
"",
true,
Constants.ephemeralNotificationType.normal,
url)
root.close() root.close()
} catch (e) { } catch (e) {

View File

@ -8,7 +8,6 @@ InviteFriendsPopup 1.0 InviteFriendsPopup.qml
ModalPopup 1.0 ModalPopup.qml ModalPopup 1.0 ModalPopup.qml
PopupMenu 1.0 PopupMenu.qml PopupMenu 1.0 PopupMenu.qml
SendModal 1.0 SendModal.qml SendModal 1.0 SendModal.qml
ToastMessage 1.0 ToastMessage.qml
TransactionModal 1.0 TransactionModal.qml TransactionModal 1.0 TransactionModal.qml
TransactionSettingsConfirmationPopup 1.0 TransactionSettingsConfirmationPopup.qml TransactionSettingsConfirmationPopup 1.0 TransactionSettingsConfirmationPopup.qml
UnblockContactConfirmationDialog 1.0 UnblockContactConfirmationDialog.qml UnblockContactConfirmationDialog 1.0 UnblockContactConfirmationDialog.qml

View File

@ -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 communityImported: 0
readonly property int communityImportingInProgress: 1 readonly property int communityImportingInProgress: 1
readonly property int communityImportingError: 2 readonly property int communityImportingError: 2

View File

@ -14,7 +14,6 @@ QtObject {
property var mainModuleInst property var mainModuleInst
property var privacyModuleInst property var privacyModuleInst
property var toastMessage
property bool profilePopupOpened: false property bool profilePopupOpened: false
property string currentNetworkId: "" property string currentNetworkId: ""
property bool networkGuarded: root.currentNetworkId === Constants.networkMainnet || property bool networkGuarded: root.currentNetworkId === Constants.networkMainnet ||
@ -29,6 +28,7 @@ QtObject {
signal openProfilePopupRequested(string publicKey, var parentPopup, bool openNicknamePopup) signal openProfilePopupRequested(string publicKey, var parentPopup, bool openNicknamePopup)
signal openChangeProfilePicPopup() signal openChangeProfilePicPopup()
signal displayToastMessage(string title, string subTitle, string icon, bool loading, int ephNotifType, string url)
function openProfilePopup(publicKey, parentPopup, openNicknamePopup){ function openProfilePopup(publicKey, parentPopup, openNicknamePopup){
openProfilePopupRequested(publicKey, parentPopup, openNicknamePopup); openProfilePopupRequested(publicKey, parentPopup, openNicknamePopup);