feat(Wallet/Toasts): Updated / added toasts related to community tokens received

- Added new role into ephemeral_notification_model: image.
- Added new view API to display ephemeral notifications with image and action.
- Added support to display asset or collectible image in a toast with different shape (circle or square).
- Default values assigned to the new parameters added in `CommunityTokensStore` meanwhile backend is not ready.
- Created page for `StatusToastMessage` in `storybook`.

Closes #13039
This commit is contained in:
Noelia 2024-01-19 12:40:41 +01:00 committed by Noelia
parent 09629985f7
commit 21a33cabd9
10 changed files with 216 additions and 22 deletions

View File

@ -13,6 +13,7 @@ type
title: string
durationInMs: int
subTitle: string
image: string
icon: string
iconColor: string
loading: bool
@ -26,6 +27,7 @@ proc initItem*(id: int64,
title: string,
durationInMs = 0,
subTitle = "",
image = "",
icon = "",
iconColor = "",
loading = false,
@ -40,6 +42,7 @@ proc initItem*(id: int64,
result.durationInMs = durationInMs
result.title = title
result.subTitle = subTitle
result.image = image
result.icon = icon
result.iconColor = iconColor
result.loading = loading
@ -64,6 +67,9 @@ proc durationInMs*(self: Item): int =
proc subTitle*(self: Item): string =
self.subTitle
proc image*(self: Item): string =
self.image
proc icon*(self: Item): string =
self.icon

View File

@ -8,6 +8,7 @@ type
DurationInMs
Title
SubTitle
Image
Icon
IconColor
Loading
@ -41,6 +42,7 @@ QtObject:
ModelRole.DurationInMs.int:"durationInMs",
ModelRole.Title.int:"title",
ModelRole.SubTitle.int:"subTitle",
ModelRole.Image.int:"image",
ModelRole.Icon.int:"icon",
ModelRole.IconColor.int:"iconColor",
ModelRole.Loading.int:"loading",
@ -69,6 +71,8 @@ QtObject:
result = newQVariant(item.title)
of ModelRole.SubTitle:
result = newQVariant(item.subTitle)
of ModelRole.Image:
result = newQVariant(item.image)
of ModelRole.Icon:
result = newQVariant(item.icon)
of ModelRole.IconColor:

View File

@ -204,6 +204,10 @@ method displayEphemeralWithActionNotification*(self: AccessInterface, title: str
ephNotifType: int, actionType: int, actionData: string, details = NotificationDetails()) {.base.} =
raise newException(ValueError, "No implementation available")
method displayEphemeralImageWithActionNotification*(self: AccessInterface, title: string, subTitle: string, image: string,
ephNotifType: int, actionType: int, actionData: string, details = NotificationDetails()) {.base.} =
raise newException(ValueError, "No implementation available")
method removeEphemeralNotification*(self: AccessInterface, id: int64) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -1312,7 +1312,7 @@ method displayEphemeralNotification*[T](self: Module[T], title: string, subTitle
elif(ephNotifType == EphemeralNotificationType.Danger.int):
finalEphNotifType = EphemeralNotificationType.Danger
let item = ephemeral_notification_item.initItem(id, title, TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS, subTitle, icon, "",
let item = ephemeral_notification_item.initItem(id, title, TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS, subTitle, "", icon, "",
loading, finalEphNotifType, url, 0, "", details)
self.view.ephemeralNotificationModel().addItem(item)
@ -1328,10 +1328,27 @@ method displayEphemeralWithActionNotification*[T](self: Module[T], title: string
elif(ephNotifType == EphemeralNotificationType.Danger.int):
finalEphNotifType = EphemeralNotificationType.Danger
let item = ephemeral_notification_item.initItem(id, title, TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS, subTitle, icon, iconColor,
let item = ephemeral_notification_item.initItem(id, title, TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS, subTitle, "", icon, iconColor,
loading, finalEphNotifType, "", actionType, actionData, details)
self.view.ephemeralNotificationModel().addItem(item)
# TO UNIFY with the one above.
# Further refactor will be done in a next step
method displayEphemeralImageWithActionNotification*[T](self: Module[T], title: string, subTitle: string, image: string, ephNotifType: int,
actionType: int, actionData: string, details = NotificationDetails()) =
let now = getTime()
let id = now.toUnix * 1000000000 + now.nanosecond
var finalEphNotifType = EphemeralNotificationType.Default
if(ephNotifType == EphemeralNotificationType.Success.int):
finalEphNotifType = EphemeralNotificationType.Success
elif(ephNotifType == EphemeralNotificationType.Danger.int):
finalEphNotifType = EphemeralNotificationType.Danger
let item = ephemeral_notification_item.initItem(id, title, TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS, subTitle, image, "", "", false,
finalEphNotifType, "", actionType, actionData, details)
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

View File

@ -124,6 +124,12 @@ QtObject:
ephNotifType: int, actionType: int, actionData: string) {.slot.} =
self.delegate.displayEphemeralWithActionNotification(title, subTitle, icon, iconColor, loading, ephNotifType, actionType, actionData)
# TO UNIFY with the one above.
# Further refactor will be done in a next step
proc displayEphemeralImageWithActionNotification*(self: View, title: string, subTitle: string, image: string, ephNotifType: int,
actionType: int, actionData: string) {.slot.} =
self.delegate.displayEphemeralImageWithActionNotification(title, subTitle, image, ephNotifType, actionType, actionData)
proc removeEphemeralNotification*(self: View, id: string) {.slot.} =
self.delegate.removeEphemeralNotification(id.parseInt)

File diff suppressed because one or more lines are too long

View File

@ -1636,10 +1636,25 @@ Item {
clip: false
delegate: StatusToastMessage {
property bool isSquare : isSquareShape(model.actionData)
// Specific method to calculate image radius depending on if the toast represents some info about a collectible or an asset
function isSquareShape(data) {
// It expects the data is a JSON file containing `tokenType`
if(data) {
var parsedData = JSON.parse(data)
var tokenType = parsedData.tokenType
return tokenType === Constants.TokenType.ERC721
}
return false
}
objectName: "statusToastMessage"
width: ListView.view.width
primaryText: model.title
secondaryText: model.subTitle
image: model.image
imageRadius: model.image && isSquare ? 8 : imageSize / 2
icon.name: model.icon
iconColor: model.iconColor
loading: model.loading

View File

@ -2,6 +2,8 @@ import QtQuick 2.15
import utils 1.0
import AppLayouts.Wallet 1.0
import AppLayouts.stores 1.0
import AppLayouts.Chat.stores 1.0 as ChatStores
@ -21,7 +23,8 @@ QtObject {
NavigateToCommunityAdmin = 1,
OpenFinaliseOwnershipPopup = 2,
OpenSendModalPopup = 3,
ViewTransactionDetails = 4
ViewTransactionDetails = 4,
OpenFirstCommunityTokenPopup = 5
}
// Stores:
@ -54,22 +57,6 @@ QtObject {
communityId)
}
function onCommunityTokenReceived(name, image, communityId, communityName, communityColor, balance, chainId, txHash) {
var data = {
communityId: communityId,
chainId: chainId,
txHash: txHash
}
Global.displayToastWithActionMessage(qsTr("You were airdropped %1 %2 asset from %3").arg(balance).arg(name).arg(communityName),
qsTr("View transaction details"),
image,
communityColor,
false,
Constants.ephemeralNotificationType.normal,
ToastsManager.ActionType.ViewTransactionDetails,
JSON.stringify(data))
}
function onSetSignerStateChanged(communityId, communityName, status, url) {
if (status === Constants.ContractTransactionStatus.Completed) {
Global.displayToastMessage(qsTr("%1 smart contract amended").arg(communityName),
@ -140,6 +127,48 @@ QtObject {
Constants.ephemeralNotificationType.danger,
"")
}
// Community token received in the user wallet:
function onCommunityTokenReceived(name, image, communityId, communityName, balance, chainId, txHash, isFirst, tokenType, walletAccountName) {
// Some error control:
if(tokenType !== Constants.TokenType.ERC20 && tokenType !== Constants.TokenType.ERC721) {
console.warn("Community token Received: Unexpected token type while creating a toast message: " + tokenType)
return
}
var data = {
communityId: communityId,
chainId: chainId,
txHash: txHash,
tokenType: tokenType
}
if(isFirst) {
var tokenTypeText = ""
if(tokenType === Constants.TokenType.ERC20) {
tokenTypeText = qsTr("You received your first community asset")
} else if(tokenType === Constants.TokenType.ERC721) {
tokenTypeText = qsTr("You received your first community collectible")
}
// First community token received toast:
Global.displayImageToastWithActionMessage(qsTr("%1: %2 %3").arg(tokenTypeText).arg(balance).arg(name),
qsTr("Learn more"),
image,
Constants.ephemeralNotificationType.normal,
ToastsManager.ActionType.OpenFirstCommunityTokenPopup,
JSON.stringify(data))
} else {
// Generic community token received toast:
Global.displayImageToastWithActionMessage(qsTr("You were airdropped %1 %2 from %3 to %4").arg(balance).arg(name).arg(communityName).arg(walletAccountName),
qsTr("View transaction details"),
image,
Constants.ephemeralNotificationType.normal,
ToastsManager.ActionType.ViewTransactionDetails,
JSON.stringify(data))
}
}
}
// Connections to global. These will lead the backend integration:
@ -155,6 +184,10 @@ QtObject {
function onDisplayToastWithActionMessage(title: string, subTitle: string, icon: string, iconColor: string, loading: bool, ephNotifType: int, actionType: int, actionData: string) {
root.rootStore.mainModuleInst.displayEphemeralWithActionNotification(title, subTitle, icon, iconColor, loading, ephNotifType, actionType, actionData)
}
function onDisplayImageToastWithActionMessage(title: string, subTitle: string, image: string, ephNotifType: int, actionType: int, actionData: string) {
root.rootStore.mainModuleInst.displayEphemeralImageWithActionNotification(title, subTitle, image, ephNotifType, actionType, actionData)
}
}
// It will cover all specific actions (different than open external links) that can be done after clicking toast link text
@ -169,6 +202,22 @@ QtObject {
case ToastsManager.ActionType.OpenSendModalPopup:
root.sendModalPopup.open()
return
case ToastsManager.ActionType.ViewTransactionDetails:
var txHash = ""
if(actionData) {
var parsedData = JSON.parse(actionData)
txHash = parsedData.txHash
Global.changeAppSectionBySectionType(Constants.appSection.wallet,
WalletLayout.LeftPanelSelection.AllAddresses,
WalletLayout.RightPanelSelection.Activity)
// TODO: Final navigation to the specific transaction entry --> {transaction: txHash}) --> Issue #13249
return
}
console.warn("Unexpected transaction hash while trying to navigate to the details page: " + txHash)
return
case ToastsManager.ActionType.OpenFirstCommunityTokenPopup:
console.warn("TODO: #12366")
return
default:
console.warn("ToastsManager: Action type is not defined")
return

View File

@ -34,7 +34,11 @@ QtObject {
signal communityOwnershipDeclined(string communityName)
signal sendOwnerTokenStateChanged(string tokenName, int status, string url)
signal ownerTokenReceived(string communityId, string communityName)
signal communityTokenReceived(string name, string image, string communityId, string communityName, string communityColor, string balance, int chainId, string txHash)
signal communityTokenReceived(string name, string image,
string communityId, string communityName,
string balance, int chainId,
string txHash, bool isFirst,
int tokenType, string walletAccountName)
// Minting tokens:
function deployCollectible(communityId, collectibleItem)
@ -132,8 +136,16 @@ QtObject {
root.ownerTokenReceived(communityId, communityName)
}
function onCommunityTokenReceived(name, image, communityId, communityName, communityColor, balance, chainId, txHash) {
root.communityTokenReceived(name, image, communityId, communityName, communityColor, balance, chainId, txHash)
function onCommunityTokenReceived(name, image, communityId, communityName, communityColor /*Unused, can be removed*/, balance, chainId, txHash/*, isFirst, tokenType, walletAccountName*/) {
// TODO BACKEND: #13250
// ** `isFirst` property will be true if it's the first time the user receives a community asset and a community collectible
// ** `tokenType` property will determine if the received minted token is an ERC20 or an ERC720
// ** `walletAccountName` property will provide the wallet account name where the token was received
var isFirst = false
var tokenType = Constants.TokenType.ERC20
var walletAccountName = "Status account"
root.communityTokenReceived(name, image, communityId, communityName, balance, chainId, txHash, isFirst, tokenType, walletAccountName)
}
function onSetSignerStateChanged(communityId, communityName, status, url) {

View File

@ -27,6 +27,7 @@ QtObject {
signal displayToastMessage(string title, string subTitle, string icon, bool loading, int ephNotifType, string url)
signal displayToastWithActionMessage(string title, string subTitle, string icon, string iconColor, bool loading, int ephNotifType, int actionType, string data)
signal displayImageToastWithActionMessage(string title, string subTitle, string image, int ephNotifType, int actionType, string data)
signal openPopupRequested(var popupComponent, var params)
signal closePopupRequested()