feat: add error management to the collectibles

plus reload button

(cherry picked from commit 718f806557ffb041263e035845a21c2f7126807c)
This commit is contained in:
Jonathan Rainville 2020-08-24 16:50:49 -04:00
parent 3219b0f5f4
commit 9eaf0a2d90
7 changed files with 199 additions and 58 deletions

View File

@ -285,37 +285,79 @@ QtObject:
$(%*{
"address": address,
"collectibleType": status_collectibles.CRYPTOKITTY,
"collectibles": status_collectibles.getCryptoKitties(address)
"collectiblesOrError": status_collectibles.getCryptoKitties(address)
})
spawnAndSend(self, "setCollectiblesResult") do:
$(%*{
"address": address,
"collectibleType": status_collectibles.KUDO,
"collectibles": status_collectibles.getKudos(address)
"collectiblesOrError": status_collectibles.getKudos(address)
})
spawnAndSend(self, "setCollectiblesResult") do:
$(%*{
"address": address,
"collectibleType": status_collectibles.ETHERMON,
"collectibles": status_collectibles.getEthermons(address)
"collectiblesOrError": status_collectibles.getEthermons(address)
})
proc setCollectiblesResult(self: WalletView, collectiblesJSON: string) {.slot.} =
let collectibleData = parseJson(collectiblesJSON)
let address = collectibleData["address"].getStr
var collectibles: JSONNode
try:
collectibles = parseJson(collectibleData["collectiblesOrError"].getStr)
except Exception as e:
# We failed parsing, this means the result is an error string
self.currentCollectiblesLists.setErrorByType(
collectibleData["collectibleType"].getStr,
$collectibleData["collectiblesOrError"]
)
return
# TODO Add the collectibleData to the Wallet account
# let index = self.accounts.getAccountindexByAddress(address)
# if index == -1: return
# self.accounts.getAccount(index).collectiblesLists = collectiblesList
if address == self.currentAccount.address:
# Add CollectibleListJSON to the right list
# TODO check if instead we need to set an error
self.currentCollectiblesLists.setCollectiblesJSONByType(
collectibleData["collectibleType"].getStr,
$collectibleData["collectibles"]
$collectibles
)
proc reloadCollectible*(self: WalletView, collectibleType: string) {.slot.} =
let address = self.currentAccount.address
# TODO find a cooler way to do this
case collectibleType:
of CRYPTOKITTY:
spawnAndSend(self, "setCollectiblesResult") do:
$(%*{
"address": address,
"collectibleType": status_collectibles.CRYPTOKITTY,
"collectiblesOrError": status_collectibles.getCryptoKitties(address)
})
of KUDO:
spawnAndSend(self, "setCollectiblesResult") do:
$(%*{
"address": address,
"collectibleType": status_collectibles.KUDO,
"collectiblesOrError": status_collectibles.getKudos(address)
})
of ETHERMON:
spawnAndSend(self, "setCollectiblesResult") do:
$(%*{
"address": address,
"collectibleType": status_collectibles.ETHERMON,
"collectiblesOrError": status_collectibles.getEthermons(address)
})
else:
error "Unrecognized collectible"
return
self.currentCollectiblesLists.setLoadingByType(collectibleType, 1)
proc loadingTrxHistory*(self: WalletView, isLoading: bool) {.signal.}
proc loadTransactionsForAccount*(self: WalletView, address: string) {.slot.} =

View File

@ -27,13 +27,41 @@ QtObject:
result.collectibleLists = @[]
result.setup
proc setLoadingByType*(self: CollectiblesList, collectibleType: string, loading: int) =
var i = 0
for collectibleList in self.collectibleLists:
if collectibleList.collectibleType == collectibleType:
collectibleList.loading = loading
let topLeft = self.createIndex(i, 0, nil)
let bottomRight = self.createIndex(i, 0, nil)
self.dataChanged(topLeft, bottomRight, @[CollectiblesRoles.Loading.int])
break
i = i + 1
proc setCollectiblesJSONByType*(self: CollectiblesList, collectibleType: string, collectiblesJSON: string) =
var i = 0
for collectibleList in self.collectibleLists:
if collectibleList.collectibleType == collectibleType:
collectibleList.collectiblesJSON = collectiblesJSON
collectibleList.loading = 0
self.forceUpdate()
collectibleList.error = ""
let topLeft = self.createIndex(i, 0, nil)
let bottomRight = self.createIndex(i, 0, nil)
self.dataChanged(topLeft, bottomRight, @[CollectiblesRoles.Loading.int, CollectiblesRoles.CollectiblesJSON.int, CollectiblesRoles.Error.int])
break
i = i + 1
proc setErrorByType*(self: CollectiblesList, collectibleType: string, error: string) =
var i = 0
for collectibleList in self.collectibleLists:
if collectibleList.collectibleType == collectibleType:
collectibleList.error = error
collectibleList.loading = 0
let topLeft = self.createIndex(i, 0, nil)
let bottomRight = self.createIndex(i, 0, nil)
self.dataChanged(topLeft, bottomRight, @[CollectiblesRoles.Loading.int, CollectiblesRoles.Error.int])
break
i = i + 1
method rowCount(self: CollectiblesList, index: QModelIndex = nil): int =
return self.collectibleLists.len

View File

@ -58,8 +58,9 @@ proc tokensOfOwnerByIndex(contract: Contract, address: EthAddress): seq[int] =
result.add(token)
index = index + 1
proc getCryptoKitties*(address: EthAddress): seq[Collectible] =
result = @[]
proc getCryptoKitties*(address: EthAddress): string =
var cryptokitties: seq[Collectible]
cryptokitties = @[]
try:
# TODO handle testnet -- does this API exist in testnet??
# TODO handle offset (recursive method?)
@ -80,7 +81,7 @@ proc getCryptoKitties*(address: EthAddress): seq[Collectible] =
finalId = $id
if (not (name.kind == JNull)):
finalName = $name
result.add(Collectible(id: finalId,
cryptokitties.add(Collectible(id: finalId,
name: finalName,
image: kitty["image_url_png"].str,
collectibleType: CRYPTOKITTY,
@ -90,21 +91,25 @@ proc getCryptoKitties*(address: EthAddress): seq[Collectible] =
error "Error with this individual cat", msg = e2.msg, cat = kitty
except Exception as e:
error "Error getting Cryptokitties", msg = e.msg
return e.msg
return $(%*cryptokitties)
proc getCryptoKitties*(address: string): seq[Collectible] =
proc getCryptoKitties*(address: string): string =
let eth_address = parseAddress(address)
result = getCryptoKitties(eth_address)
proc getEthermons*(address: EthAddress): seq[Collectible] =
result = @[]
proc getEthermons*(address: EthAddress): string =
try:
var ethermons: seq[Collectible]
ethermons = @[]
let contract = getContract("ethermon")
if contract == nil: return
let tokens = tokensOfOwnerByIndex(contract, address)
if (tokens.len == 0):
return result
return $(%*ethermons)
let tokensJoined = strutils.join(tokens, ",")
let url = fmt"https://www.ethermon.io/api/monster/get_data?monster_ids={tokensJoined}"
@ -116,36 +121,40 @@ proc getEthermons*(address: EthAddress): seq[Collectible] =
var i = 0
for monsterKey in json.keys(monsters):
let monster = monsters[monsterKey]
result.add(Collectible(id: $tokens[i],
ethermons.add(Collectible(id: $tokens[i],
name: monster["class_name"].str,
image: monster["image"].str,
collectibleType: ETHERMON,
description: "",
externalUrl: ""))
i = i + 1
return $(%*ethermons)
except Exception as e:
error "Error getting Ethermons", msg = e.msg
result = e.msg
proc getEthermons*(address: string): seq[Collectible] =
proc getEthermons*(address: string): string =
let eth_address = parseAddress(address)
result = getEthermons(eth_address)
proc getKudos*(address: EthAddress): seq[Collectible] =
result = @[]
proc getKudos*(address: EthAddress): string =
try:
var kudos: seq[Collectible]
kudos = @[]
let contract = getContract("kudos")
if contract == nil: return
let tokens = tokensOfOwnerByIndex(contract, address)
if (tokens.len == 0):
return result
return $(%*kudos)
for token in tokens:
let url = getTokenUri(contract, token.u256)
if (url == ""):
return result
return $(%*kudos)
let client = newHttpClient()
client.headers = newHttpHeaders({ "Content-Type": "application/json" })
@ -153,15 +162,18 @@ proc getKudos*(address: EthAddress): seq[Collectible] =
let response = client.request(url)
let kudo = parseJson(response.body)
result.add(Collectible(id: $token,
kudos.add(Collectible(id: $token,
name: kudo["name"].str,
image: kudo["image"].str,
collectibleType: KUDO,
description: kudo["description"].str,
externalUrl: kudo["external_url"].str))
return $(%*kudos)
except Exception as e:
error "Error getting Kudos", msg = e.msg
result = e.msg
proc getKudos*(address: string): seq[Collectible] =
proc getKudos*(address: string): string =
let eth_address = parseAddress(address)
result = getKudos(eth_address)

View File

@ -60,6 +60,13 @@ Item {
}
}
}
Connections {
target: walletModel.collectiblesLists
onDataChanged: {
checkCollectiblesVisibility()
}
}
}
/*##^##

View File

@ -6,14 +6,21 @@ import "../../../../../shared"
Item {
property url collectibleIconSource: "../../../../img/collectibles/CryptoKitties.png"
property string collectibleName: "CryptoKitties"
property string collectibleType: "cryptokitty"
property bool collectiblesOpened: false
property var collectiblesModal
property string buttonText: "View in Cryptokitties"
property var getLink: function () {}
property var collectibles: {
if (error) {
return []
}
try {
return JSON.parse(collectiblesJSON)
var result = JSON.parse(collectiblesJSON)
if (typeof result === "string") {
return JSON.parse(result)
}
return result
} catch (e) {
console.error('Error parsing collectibles for:', collectibleName)
console.error('JSON:', collectiblesJSON)
@ -22,7 +29,7 @@ Item {
}
}
// Adding active instead of just using visible, because visible counts as false when the parent is not visible
property bool active: !!loading || collectibles.length > 0
property bool active: !!loading || !!error || collectibles.length > 0
id: root
visible: active
@ -44,7 +51,6 @@ Item {
id: collectiblesContent
visible: root.collectiblesOpened
collectiblesModal: root.collectiblesModal
collectibleType: root.collectibleType
buttonText: root.buttonText
getLink: root.getLink
anchors.top: collectiblesHeader.bottom

View File

@ -7,55 +7,101 @@ import "../../../../../shared"
ScrollView {
readonly property int imageSize: 164
property string collectibleType: "cryptokitty"
property var collectiblesModal
property string buttonText: "View in Cryptokitties"
property var getLink: function () {}
property var collectibles: []
id: root
height: visible ? contentRow.height : 0
height: visible ? contentLoader.item.height : 0
width: parent.width
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
ScrollBar.horizontal.policy: ScrollBar.AsNeeded
clip: true
Row {
id: contentRow
bottomPadding: Style.current.padding
spacing: Style.current.padding
Loader {
id: contentLoader
active: true
width: parent.width
height: root.imageSize
sourceComponent: !!error ? errorComponent : collectiblesContentComponent
}
Repeater {
model: collectibles
Component {
id: errorComponent
Rectangle {
radius: 16
border.width: 1
border.color: Style.current.border
color: Style.current.background
width: collectibleImage.width
height: collectibleImage.height
Item {
width: parent.width
height: root.imageSize
Image {
id: collectibleImage
width: root.imageSize
height: root.imageSize
source: modelData.image
fillMode: Image.PreserveAspectCrop
Item {
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
height: childrenRect.height
width: somethingWentWrongText.width
StyledText {
id: somethingWentWrongText
text: qsTr("Something went wrong")
anchors.horizontalCenter: parent.horizontalCenter
color: Style.current.secondaryText
font.pixelSize: 13
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
StyledButton {
label: qsTr("Reload")
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: somethingWentWrongText.bottom
anchors.topMargin: Style.current.halfPadding
onClicked: {
collectiblesModal.openModal({
name: modelData.name,
id: modelData.id,
description: modelData.description,
buttonText: root.buttonText,
link: root.getLink(modelData.id, modelData.externalUrl),
image: modelData.image
})
walletModel.reloadCollectible(collectibleType)
}
}
}
}
}
Component {
id: collectiblesContentComponent
Row {
id: contentRow
bottomPadding: Style.current.padding
spacing: Style.current.padding
Repeater {
model: collectibles
Rectangle {
radius: 16
border.width: 1
border.color: Style.current.border
color: Style.current.background
width: collectibleImage.width
height: collectibleImage.height
Image {
id: collectibleImage
width: root.imageSize
height: root.imageSize
source: modelData.image
fillMode: Image.PreserveAspectCrop
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
collectiblesModal.openModal({
name: modelData.name,
id: modelData.id,
description: modelData.description,
buttonText: root.buttonText,
link: root.getLink(modelData.id, modelData.externalUrl),
image: modelData.image
})
}
}
}
}

View File

@ -60,7 +60,7 @@ Rectangle {
StyledText {
id: numberCollectibleText
color: Style.current.secondaryText
text: collectibleHeader.collectiblesQty
text: !!error ? "-" : collectibleHeader.collectiblesQty
font.pixelSize: 15
anchors.verticalCenter: parent.verticalCenter
}