fix(wallet): Update collectibles media management (#16080)

This commit is contained in:
Cuteivist 2024-08-28 15:58:33 +02:00 committed by GitHub
parent ef9c2598cc
commit 658fe2a5b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 271 additions and 63 deletions

View File

@ -348,6 +348,14 @@ QtObject:
read = getTwitterHandle read = getTwitterHandle
notify = twitterHandleChanged notify = twitterHandleChanged
proc isMetadataValidChanged*(self: CollectiblesEntry) {.signal.}
proc getIsMetaDataValid*(self: CollectiblesEntry): bool {.slot.} =
return self.hasCollectibleData()
QtProperty[bool] isMetadataValid:
read = getIsMetaDataValid
notify = isMetadataValidChanged
proc updateDataIfSameID*(self: CollectiblesEntry, update: backend.Collectible): bool = proc updateDataIfSameID*(self: CollectiblesEntry, update: backend.Collectible): bool =
if self.id != update.id: if self.id != update.id:
return false return false

View File

@ -39,8 +39,8 @@ QtObject:
read = getDetailedEntry read = getDetailedEntry
notify = detailedEntryChanged notify = detailedEntryChanged
proc getIsDetailedEntryLoading*(self: Controller): QVariant {.slot.} = proc getIsDetailedEntryLoading*(self: Controller): bool {.slot.} =
return newQVariant(self.detailedEntry) return self.isDetailedEntryLoading
proc isDetailedEntryLoadingChanged(self: Controller) {.signal.} proc isDetailedEntryLoadingChanged(self: Controller) {.signal.}

View File

@ -0,0 +1,129 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import Storybook 1.0
import AppLayouts.Communities.stores 1.0 as CommunitiesStores
import AppLayouts.Wallet 1.0
import AppLayouts.Wallet.stores 1.0 as WalletStores
import AppLayouts.Wallet.views.collectibles 1.0
import StatusQ.Core.Utils 0.1
import shared.controls 1.0
import shared.stores 1.0 as SharedStores
import Models 1.0
import utils 1.0
SplitView {
id: root
// QtObject {
// function isValidURL(url) {
// return true
// }
// Component.onCompleted: {
// Utils.globalUtilsInst = this
// }
// Component.onDestruction: {
// Utils.globalUtilsInst = {}
// }
// }
QtObject {
id: d
readonly property QtObject collectiblesModel: ManageCollectiblesModel {
Component.onCompleted: {
d.refreshCurrentCollectible()
}
}
property var currentCollectible
function refreshCurrentCollectible() {
currentCollectible = ModelUtils.get(collectiblesModel, collectibleComboBox.currentIndex)
}
}
SplitView {
orientation: Qt.Vertical
SplitView.fillWidth: true
Item {
SplitView.fillWidth: true
SplitView.fillHeight: true
Rectangle {
anchors.fill: viewLoader
anchors.margins: -1
color: "transparent"
border.width: 1
border.color: "#808080"
}
Loader {
id: viewLoader
anchors.fill: parent
anchors.margins: 50
active: false
sourceComponent: CollectibleMedia {
backgroundColor: d.currentCollectible.backgroundColor
isCollectibleLoading: isLoadingCheckbox.checked
isMetadataValid: !d.currentCollectible.isMetadataValid
mediaUrl: d.currentCollectible.mediaUrl ?? ""
fallbackImageUrl: d.currentCollectible.imageUrl
interactive: isInteractiveCheckbox.checked
enabled: isEnabledCheckbox.checked
}
Component.onCompleted: viewLoader.active = true
}
}
LogsAndControlsPanel {
SplitView.minimumHeight: 100
SplitView.preferredHeight: 150
SplitView.fillWidth: true
}
}
Pane {
SplitView.minimumWidth: 300
SplitView.preferredWidth: 300
ColumnLayout {
Label {
text: "Collectible:"
}
ComboBox {
id: collectibleComboBox
Layout.fillWidth: true
textRole: "name"
model: d.collectiblesModel
currentIndex: 0
onCurrentIndexChanged: d.refreshCurrentCollectible()
}
CheckBox { // Loading state when model is loading, it doesn't affect internal image loading state
id: isLoadingCheckbox
text: "isLoading"
checked: false
}
CheckBox {
id: isInteractiveCheckbox
text: "isInteractive"
checked: true
}
CheckBox {
id: isEnabledCheckbox
text: "isEnabled"
checked: true
}
}
}
}
// category: Wallet

View File

@ -134,7 +134,7 @@ Item {
const lvOther = findChild(controlUnderTest, "otherTokensListView") const lvOther = findChild(controlUnderTest, "otherTokensListView")
verify(!!lvOther) verify(!!lvOther)
tryCompare(lvOther, "count", 9) tryCompare(lvOther, "count", 10)
const delegate0 = findChild(lvOther, "manageTokensDelegate-0") const delegate0 = findChild(lvOther, "manageTokensDelegate-0")
verify(!!delegate0) verify(!!delegate0)
const title = delegate0.title const title = delegate0.title
@ -144,7 +144,7 @@ Item {
tryCompare(notificationSpy, "count", 1) tryCompare(notificationSpy, "count", 1)
// verify we now have -1 regular tokens after the "hide" operation // verify we now have -1 regular tokens after the "hide" operation
tryCompare(lvOther, "count", 8) tryCompare(lvOther, "count", 9)
} }
function test_showHideCommunityGroup() { function test_showHideCommunityGroup() {

View File

@ -64,7 +64,8 @@ ListModel {
], ],
tokenId: "403", tokenId: "403",
twitterHandle: "@punxNotDead", twitterHandle: "@punxNotDead",
website: "www.punxnotdead.com" website: "www.punxnotdead.com",
isMetadataValid: true
}, },
{ {
uid: "pp23", uid: "pp23",
@ -109,7 +110,8 @@ ListModel {
], ],
tokenId: "123", tokenId: "123",
twitterHandle: "@pepepunks", twitterHandle: "@pepepunks",
website: "www.pepepunks.com" website: "www.pepepunks.com",
isMetadataValid: true
}, },
{ {
uid: "34545656768", uid: "34545656768",
@ -154,7 +156,8 @@ ListModel {
], ],
tokenId: "7123", tokenId: "7123",
twitterHandle: "@kitties", twitterHandle: "@kitties",
website: "www.kitties.com" website: "www.kitties.com",
isMetadataValid: true
}, },
{ {
uid: "123456", uid: "123456",
@ -202,7 +205,8 @@ ListModel {
], ],
tokenId: "403123", tokenId: "403123",
twitterHandle: "", twitterHandle: "",
website: "www.kitties.com" website: "www.kitties.com",
isMetadataValid: true
}, },
{ {
uid: "12345645459537432", uid: "12345645459537432",
@ -252,7 +256,8 @@ ListModel {
], ],
tokenId: "1", tokenId: "1",
twitterHandle: "@kitties", twitterHandle: "@kitties",
website: "" website: "",
isMetadataValid: true
}, },
{ {
uid: "pp21", uid: "pp21",
@ -289,7 +294,8 @@ ListModel {
], ],
tokenId: "12568", tokenId: "12568",
twitterHandle: "@pepepunks", twitterHandle: "@pepepunks",
website: "www.pepepunks.com" website: "www.pepepunks.com",
isMetadataValid: true
}, },
{ {
uid: "lp#666a", uid: "lp#666a",
@ -326,8 +332,42 @@ ListModel {
], ],
tokenId: "1445", tokenId: "1445",
twitterHandle: "@lonelyPanda", twitterHandle: "@lonelyPanda",
website: "www.lonelyPanda.com" website: "www.lonelyPanda.com",
isMetadataValid: true
}, },
{
uid: "invalid#123",
chainId: 421613,
userHas: 0,
name: "",
collectionUid: "",
collectionName: "",
collectionImageUrl: "",
communityId: "",
communityName: "",
communityImage: "",
imageUrl: "",
isLoading: false,
backgroundColor: "",
permalink:"",
domain:"",
ownership: [
{
accountAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
balance: "1",
txTimestamp: 19
},
],
networkShortName: "OPT",
networkColor: "red",
networkIconUrl: ModelsData.networks.optimism,
description: "",
traits: [],
tokenId: "2121",
twitterHandle: "",
website: "",
isMetadataValid: false
}
] ]
readonly property var communityData: [ readonly property var communityData: [
@ -356,7 +396,8 @@ ListModel {
networkIconUrl: ModelsData.networks.optimism, networkIconUrl: ModelsData.networks.optimism,
description: "Frenly Pandas is a community for all the fiendly pandas! Welcome onboard and enjoy :)", description: "Frenly Pandas is a community for all the fiendly pandas! Welcome onboard and enjoy :)",
traits: [], traits: [],
tokenId: "4" tokenId: "4",
isMetadataValid: true
}, },
{ {
uid: "691", uid: "691",
@ -383,7 +424,8 @@ ListModel {
networkIconUrl: ModelsData.networks.optimism, networkIconUrl: ModelsData.networks.optimism,
description: "Bearz is a community for all the ferocious Bearz! Welcome onboard and enjoy :)", description: "Bearz is a community for all the ferocious Bearz! Welcome onboard and enjoy :)",
traits: [], traits: [],
tokenId: "3" tokenId: "3",
isMetadataValid: true
}, },
{ {
uid: "8876", uid: "8876",
@ -410,7 +452,8 @@ ListModel {
networkIconUrl: ModelsData.networks.ethereum, networkIconUrl: ModelsData.networks.ethereum,
description: "Bearz is a community for all the ferocious Bearz! Welcome onboard and enjoy :)", description: "Bearz is a community for all the ferocious Bearz! Welcome onboard and enjoy :)",
traits: [], traits: [],
tokenId: "341" tokenId: "341",
isMetadataValid: true
}, },
{ {
uid: "fp#3195", uid: "fp#3195",
@ -437,7 +480,8 @@ ListModel {
networkIconUrl: ModelsData.networks.ethereum, networkIconUrl: ModelsData.networks.ethereum,
description: "Frenly Pandas is a community for all the fiendly pandas! Welcome onboard and enjoy :)", description: "Frenly Pandas is a community for all the fiendly pandas! Welcome onboard and enjoy :)",
traits: [], traits: [],
tokenId: "765" tokenId: "765",
isMetadataValid: true
}, },
{ {
uid: "fp#4297", uid: "fp#4297",
@ -464,7 +508,8 @@ ListModel {
networkIconUrl: ModelsData.networks.ethereum, networkIconUrl: ModelsData.networks.ethereum,
description: "Frenly Pandas is a community for all the fiendly pandas! Welcome onboard and enjoy :)", description: "Frenly Pandas is a community for all the fiendly pandas! Welcome onboard and enjoy :)",
traits: [], traits: [],
tokenId: "166" tokenId: "166",
isMetadataValid: true
}, },
{ {
uid: "fp#909", uid: "fp#909",
@ -491,7 +536,8 @@ ListModel {
networkIconUrl: ModelsData.networks.optimism, networkIconUrl: ModelsData.networks.optimism,
description: "Frenly Pandas is a community for all the fiendly pandas! Welcome onboard and enjoy :)", description: "Frenly Pandas is a community for all the fiendly pandas! Welcome onboard and enjoy :)",
traits: [], traits: [],
tokenId: "1111" tokenId: "1111",
isMetadataValid: true
}, },
{ {
uid: "lb#666", uid: "lb#666",
@ -523,7 +569,8 @@ ListModel {
networkIconUrl: ModelsData.networks.optimism, networkIconUrl: ModelsData.networks.optimism,
description: "Bearz is a community for all the ferocious Bearz! Welcome onboard and enjoy", description: "Bearz is a community for all the ferocious Bearz! Welcome onboard and enjoy",
traits: [], traits: [],
tokenId: "6" tokenId: "6",
isMetadataValid: true
}, },
{ {
uid: "lb#777", uid: "lb#777",
@ -550,7 +597,8 @@ ListModel {
networkIconUrl: ModelsData.networks.optimism, networkIconUrl: ModelsData.networks.optimism,
description: "Lonely Turtle is a community for all of us to talk and communicate! Welcome onboard and enjoy", description: "Lonely Turtle is a community for all of us to talk and communicate! Welcome onboard and enjoy",
traits: [], traits: [],
tokenId: "7" tokenId: "7",
isMetadataValid: true
}, },
{ {
uid: "ID-Custom", uid: "ID-Custom",
@ -575,7 +623,8 @@ ListModel {
communityId: "", communityId: "",
networkShortName: "ARB", networkShortName: "ARB",
networkColor: "blue", networkColor: "blue",
networkIconUrl: ModelsData.networks.arbitrum networkIconUrl: ModelsData.networks.arbitrum,
isMetadataValid: true
}, },
{ {
uid: "ID-MissingMetadata", uid: "ID-MissingMetadata",
@ -600,7 +649,8 @@ ListModel {
communityId: "", communityId: "",
networkShortName: "OPT", networkShortName: "OPT",
networkColor: "red", networkColor: "red",
networkIconUrl: ModelsData.networks.optimism networkIconUrl: ModelsData.networks.optimism,
isMetadataValid: true
}, },
{ {
uid: "ID-Community1", uid: "ID-Community1",
@ -625,7 +675,8 @@ ListModel {
communityId: "community-id-1", communityId: "community-id-1",
networkShortName: "OPT", networkShortName: "OPT",
networkColor: "red", networkColor: "red",
networkIconUrl: ModelsData.networks.optimism networkIconUrl: ModelsData.networks.optimism,
isMetadataValid: true
}, },
{ {
uid: "ID-Community-Unknown", uid: "ID-Community-Unknown",
@ -650,7 +701,8 @@ ListModel {
communityId: "community-id-unknown", communityId: "community-id-unknown",
networkShortName: "OPT", networkShortName: "OPT",
networkColor: "red", networkColor: "red",
networkIconUrl: ModelsData.networks.optimism networkIconUrl: ModelsData.networks.optimism,
isMetadataValid: true
} }
] ]

View File

@ -238,7 +238,7 @@ StatusScrollView {
delegate: CollectibleView { delegate: CollectibleView {
height: collectiblesGrid.cellHeight height: collectiblesGrid.cellHeight
width: collectiblesGrid.cellWidth width: collectiblesGrid.cellWidth
title: model.name ? model.name : "..." title: model.name ?? ""
subTitle: deployState === Constants.ContractTransactionStatus.Completed ? subTitle: deployState === Constants.ContractTransactionStatus.Completed ?
d.getRemainingInfo(model.privilegesLevel === Constants.TokenPrivilegesLevel.Owner, d.getRemainingInfo(model.privilegesLevel === Constants.TokenPrivilegesLevel.Owner,
model.privilegesLevel === Constants.TokenPrivilegesLevel.TMaster, model.privilegesLevel === Constants.TokenPrivilegesLevel.TMaster,
@ -251,6 +251,7 @@ StatusScrollView {
fallbackImageUrl: model.image ? model.image : "" fallbackImageUrl: model.image ? model.image : ""
backgroundColor: "transparent" backgroundColor: "transparent"
isLoading: false isLoading: false
isMetadataValid: true
navigationIconVisible: false navigationIconVisible: false
privilegesLevel: model.privilegesLevel privilegesLevel: model.privilegesLevel
ornamentColor: model.color ornamentColor: model.color

View File

@ -92,7 +92,7 @@ ColumnLayout {
clear() clear()
if (d.isLoading) { if (d.isLoading) {
for (let i = 0; i < 10; i++) { for (let i = 0; i < 10; i++) {
append({ isLoading: true }) append({ isLoading: true, name: qsTr("Loading collectible...") })
} }
} }
} }
@ -497,13 +497,14 @@ ColumnLayout {
CollectibleView { CollectibleView {
width: d.cellWidth width: d.cellWidth
height: isCommunityCollectible ? d.communityCellHeight : d.cellHeight height: isCommunityCollectible ? d.communityCellHeight : d.cellHeight
title: model.name ? model.name : "..." title: model.name ?? ""
subTitle: model.collectionName ? model.collectionName : model.collectionUid ? model.collectionUid : "" subTitle: model.collectionName ? model.collectionName : model.collectionUid ? model.collectionUid : ""
mediaUrl: model.mediaUrl ?? "" mediaUrl: model.mediaUrl ?? ""
mediaType: model.mediaType ?? "" mediaType: model.mediaType ?? ""
fallbackImageUrl: model.imageUrl ?? "" fallbackImageUrl: model.imageUrl ?? ""
backgroundColor: model.backgroundColor ? model.backgroundColor : "transparent" backgroundColor: model.backgroundColor ? model.backgroundColor : "transparent"
isLoading: !!model.isLoading isLoading: !!model.isLoading
isMetadataValid: !!model.isMetadataValid
privilegesLevel: model.communityPrivilegesLevel ?? Constants.TokenPrivilegesLevel.Community privilegesLevel: model.communityPrivilegesLevel ?? Constants.TokenPrivilegesLevel.Community
ornamentColor: model.communityColor ?? "transparent" ornamentColor: model.communityColor ?? "transparent"
communityId: model.communityId ?? "" communityId: model.communityId ?? ""

View File

@ -361,11 +361,11 @@ Item {
Component { Component {
id: collectibleimageComponent id: collectibleimageComponent
StatusRoundedMedia { CollectibleMedia {
id: collectibleImage id: collectibleImage
readonly property bool isEmpty: !mediaUrl.toString() && !fallbackImageUrl.toString() backgroundColor: collectible.backgroundColor
radius: Style.current.radius isCollectibleLoading: root.isCollectibleLoading
color: isError || isEmpty ? Theme.palette.baseColor5 : collectible.backgroundColor isMetadataValid: !collectible.isMetadataValid
mediaUrl: collectible.mediaUrl ?? "" mediaUrl: collectible.mediaUrl ?? ""
mediaType: !!collectible ? (modelIndex > 0 && collectible.mediaType.startsWith("video")) ? "" : collectible.mediaType: "" mediaType: !!collectible ? (modelIndex > 0 && collectible.mediaType.startsWith("video")) ? "" : collectible.mediaType: ""
fallbackImageUrl: collectible.imageUrl fallbackImageUrl: collectible.imageUrl
@ -377,29 +377,6 @@ Item {
onOpenImageContextMenu: (url, isGif) => Global.openMenu(imageContextMenu, collectibleImage, { imageSource: url, isGif: isGif, isVideo: false }) onOpenImageContextMenu: (url, isGif) => Global.openMenu(imageContextMenu, collectibleImage, { imageSource: url, isGif: isGif, isVideo: false })
onOpenVideoContextMenu: (url) => Global.openMenu(imageContextMenu, collectibleImage, { imageSource: url, url: url, isVideo: true, isGif: false }) onOpenVideoContextMenu: (url) => Global.openMenu(imageContextMenu, collectibleImage, { imageSource: url, url: url, isVideo: true, isGif: false })
Loader {
anchors.fill: parent
active: collectibleImage.isLoading
sourceComponent: LoadingComponent {radius: collectibleImage.radius}
}
Loader {
anchors.fill: parent
active: collectibleImage.isError || collectibleImage.isEmpty
sourceComponent: LoadingErrorComponent {
radius: collectibleImage.radius
text: {
if (collectibleImage.isError && collectibleImage.componentMediaType === StatusRoundedMedia.MediaType.Unkown) {
return qsTr("Unsupported\nfile format")
}
if (!collectible.description && !collectible.name) {
return qsTr("Info can't\nbe fetched")
}
return qsTr("Failed\nto load")
}
}
}
Component { Component {
id: imageContextMenu id: imageContextMenu
ImageContextMenu { ImageContextMenu {

View File

@ -0,0 +1,42 @@
import QtQuick 2.14
import StatusQ.Components 0.1
import StatusQ.Core.Theme 0.1
import utils 1.0
StatusRoundedMedia {
id: root
readonly property bool isEmpty: !mediaUrl.toString() && !fallbackImageUrl.toString()
property color backgroundColor: Theme.palette.baseColor5
property bool isCollectibleLoading: false
property bool isMetadataValid: false
radius: Style.current.radius
color: isError || isEmpty ? Theme.palette.baseColor5 : backgroundColor
Loader {
id: loadingCompLoader
anchors.fill: parent
active: root.isCollectibleLoading || root.isLoading
sourceComponent: LoadingComponent {radius: root.radius}
}
Loader {
anchors.fill: parent
active: (root.isError || root.isEmpty) && !loadingCompLoader.active
sourceComponent: LoadingErrorComponent {
radius: root.radius
text: {
if (root.isError && root.componentMediaType === StatusRoundedMedia.MediaType.Unkown) {
return qsTr("Unsupported\nfile format")
}
if (!root.isMetadataValid) {
return qsTr("Info can't\nbe fetched")
}
return qsTr("Failed\nto load")
}
}
}
}

View File

@ -16,6 +16,7 @@ Control {
id: root id: root
property string title: "" property string title: ""
property string unknownTitle: "..."
property string subTitle: "" property string subTitle: ""
property alias subTitleColor: subTitleItem.customColor property alias subTitleColor: subTitleItem.customColor
property string backgroundColor: "transparent" property string backgroundColor: "transparent"
@ -24,6 +25,7 @@ Control {
property url fallbackImageUrl : "" property url fallbackImageUrl : ""
property bool isLoading: false property bool isLoading: false
property bool navigationIconVisible: false property bool navigationIconVisible: false
property bool isMetadataValid: false
property string communityId: "" property string communityId: ""
property string communityName property string communityName
property string communityImage property string communityImage
@ -77,7 +79,7 @@ Control {
contentItem: ColumnLayout { contentItem: ColumnLayout {
spacing: 0 spacing: 0
StatusRoundedMedia { CollectibleMedia {
id: image id: image
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
@ -85,21 +87,16 @@ Control {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: width Layout.preferredHeight: width
backgroundColor: root.isLoading ? "transparent" : root.backgroundColor
visible: !specialCollectible.visible visible: !specialCollectible.visible
radius: Style.current.radius isMetadataValid: root.isMetadataValid
mediaUrl: root.mediaUrl mediaUrl: root.mediaUrl
mediaType: root.mediaType mediaType: root.mediaType
fallbackImageUrl: root.fallbackImageUrl fallbackImageUrl: root.fallbackImageUrl
showLoadingIndicator: true showLoadingIndicator: true
color: root.isLoading ? "transparent" : root.backgroundColor isCollectibleLoading: root.isLoading
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
Loader {
anchors.fill: parent
active: root.isLoading
sourceComponent: LoadingComponent {radius: image.radius}
}
Loader { Loader {
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
@ -150,7 +147,7 @@ Control {
customColor: Theme.palette.directColor1 customColor: Theme.palette.directColor1
font.weight: Font.DemiBold font.weight: Font.DemiBold
elide: Text.ElideRight elide: Text.ElideRight
text: root.isLoading ? Constants.dummyText : root.title text: root.isLoading ? Constants.dummyText : root.title || root.unknownTitle
loading: root.isLoading loading: root.isLoading
} }

View File

@ -1,2 +1,3 @@
CollectibleDetailView 1.0 CollectibleDetailView.qml CollectibleDetailView 1.0 CollectibleDetailView.qml
CollectibleView 1.0 CollectibleView.qml CollectibleView 1.0 CollectibleView.qml
CollectibleMedia 1.0 CollectibleMedia.qml