diff --git a/.gitignore b/.gitignore
index f45572c388..1ffb93fe80 100644
--- a/.gitignore
+++ b/.gitignore
@@ -85,4 +85,7 @@ npm-debug.log
android/app/src/main/assets
# Resource binary file
-interface/compiledResources
\ No newline at end of file
+interface/compiledResources
+
+# GPUCache
+interface/resources/GPUCache/*
\ No newline at end of file
diff --git a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml
index 421fa4b074..f493747c5e 100644
--- a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml
+++ b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml
@@ -19,21 +19,31 @@ import "../../../controls-uit" as HifiControlsUit
import "../../../controls" as HifiControls
import "../wallet" as HifiWallet
-// references XXX from root context
-
Rectangle {
HifiConstants { id: hifi; }
id: root;
- property string marketplaceUrl;
- property string certificateId;
+ property string marketplaceUrl: "";
+ property string entityId: "";
+ property string certificateId: "";
property string itemName: "--";
property string itemOwner: "--";
property string itemEdition: "--";
property string dateOfPurchase: "--";
+ property string itemCost: "--";
+ property string certTitleTextColor: hifi.colors.darkGray;
+ property string certTextColor: hifi.colors.white;
+ property string infoTextColor: hifi.colors.blueAccent;
+ // 0 means replace none
+ // 4 means replace all but "Item Edition"
+ // 5 means replace all 5 replaceable fields
+ property int certInfoReplaceMode: 5;
property bool isLightbox: false;
property bool isMyCert: false;
- property bool isCertificateInvalid: false;
+ property bool useGoldCert: true;
+ property bool certificateInfoPending: true;
+ property int certificateStatus: 0;
+ property bool certificateStatusPending: true;
// Style
color: hifi.colors.faintGray;
Connections {
@@ -45,72 +55,135 @@ Rectangle {
} else {
root.marketplaceUrl = result.data.marketplace_item_url;
root.isMyCert = result.isMyCert ? result.isMyCert : false;
- root.itemOwner = root.isCertificateInvalid ? "--" : (root.isMyCert ? Account.username :
- "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022");
- root.itemEdition = root.isCertificateInvalid ? "Uncertified Copy" :
- (result.data.edition_number + "/" + (result.data.limited_run === -1 ? "\u221e" : result.data.limited_run));
- root.dateOfPurchase = root.isCertificateInvalid ? "" : getFormattedDate(result.data.transfer_created_at * 1000);
- root.itemName = result.data.marketplace_item_name;
+
+ if (root.certInfoReplaceMode > 3) {
+ root.itemName = result.data.marketplace_item_name;
+ // "\u2022" is the Unicode character 'BULLET' - it's what's used in password fields on the web, etc
+ root.itemOwner = root.isMyCert ? Account.username :
+ "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
+ root.dateOfPurchase = root.isMyCert ? getFormattedDate(result.data.transfer_created_at * 1000) : "Undisclosed";
+ root.itemCost = (root.isMyCert && result.data.cost !== undefined) ? result.data.cost : "Undisclosed";
+ }
+ if (root.certInfoReplaceMode > 4) {
+ root.itemEdition = result.data.edition_number + "/" + (result.data.limited_run === -1 ? "\u221e" : result.data.limited_run);
+ }
+
+ if (root.certificateStatus === 4) { // CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED
+ if (root.isMyCert) {
+ errorText.text = "This item is an uncertified copy of an item you purchased.";
+ } else {
+ errorText.text = "The person who placed this item doesn't own it.";
+ }
+ }
if (result.data.invalid_reason || result.data.transfer_status[0] === "failed") {
- titleBarText.text = "Invalid Certificate";
- titleBarText.color = hifi.colors.redHighlight;
+ root.useGoldCert = false;
+ root.certTitleTextColor = hifi.colors.redHighlight;
+ root.certTextColor = hifi.colors.redHighlight;
+ root.infoTextColor = hifi.colors.redHighlight;
+ titleBarText.text = "Certificate\nNo Longer Valid";
popText.text = "";
+ showInMarketplaceButton.visible = false;
+ // "Edition" text previously set above in this function
+ // "Owner" text previously set above in this function
+ // "Purchase Date" text previously set above in this function
+ // "Purchase Price" text previously set above in this function
if (result.data.invalid_reason) {
errorText.text = result.data.invalid_reason;
}
} else if (result.data.transfer_status[0] === "pending") {
+ root.useGoldCert = false;
+ root.certTitleTextColor = hifi.colors.redHighlight;
+ root.certTextColor = hifi.colors.redHighlight;
+ root.infoTextColor = hifi.colors.redHighlight;
titleBarText.text = "Certificate Pending";
+ popText.text = "";
+ showInMarketplaceButton.visible = true;
+ // "Edition" text previously set above in this function
+ // "Owner" text previously set above in this function
+ // "Purchase Date" text previously set above in this function
+ // "Purchase Price" text previously set above in this function
errorText.text = "The status of this item is still pending confirmation. If the purchase is not confirmed, " +
"this entity will be cleaned up by the domain.";
- errorText.color = hifi.colors.baseGray;
}
}
+ root.certificateInfoPending = false;
}
onUpdateCertificateStatus: {
- if (certStatus === 1) { // CERTIFICATE_STATUS_VERIFICATION_SUCCESS
- // NOP
- } else if (certStatus === 2) { // CERTIFICATE_STATUS_VERIFICATION_TIMEOUT
- root.isCertificateInvalid = true;
- errorText.text = "Verification of this certificate timed out.";
- errorText.color = hifi.colors.redHighlight;
- } else if (certStatus === 3) { // CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED
- root.isCertificateInvalid = true;
- titleBarText.text = "Invalid Certificate";
- titleBarText.color = hifi.colors.redHighlight;
-
- popText.text = "";
- root.itemOwner = "";
- dateOfPurchaseHeader.text = "";
- root.dateOfPurchase = "";
- root.itemEdition = "Uncertified Copy";
-
- errorText.text = "The information associated with this item has been modified and it no longer matches the original certified item.";
- errorText.color = hifi.colors.baseGray;
- } else if (certStatus === 4) { // CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED
- root.isCertificateInvalid = true;
- titleBarText.text = "Invalid Certificate";
- titleBarText.color = hifi.colors.redHighlight;
-
- popText.text = "";
- root.itemOwner = "";
- dateOfPurchaseHeader.text = "";
- root.dateOfPurchase = "";
- root.itemEdition = "Uncertified Copy";
-
- errorText.text = "The avatar who rezzed this item doesn't own it.";
- errorText.color = hifi.colors.baseGray;
- } else {
- console.log("Unknown certificate status received from ledger signal!");
- }
+ updateCertificateStatus(certStatus);
}
}
- onCertificateIdChanged: {
- if (certificateId !== "") {
- Commerce.certificateInfo(certificateId);
+ function updateCertificateStatus(status) {
+ root.certificateStatus = status;
+ if (root.certificateStatus === 1) { // CERTIFICATE_STATUS_VERIFICATION_SUCCESS
+ root.useGoldCert = true;
+ root.certTitleTextColor = hifi.colors.darkGray;
+ root.certTextColor = hifi.colors.white;
+ root.infoTextColor = hifi.colors.blueAccent;
+ titleBarText.text = "Certificate";
+ popText.text = "PROOF OF PROVENANCE";
+ showInMarketplaceButton.visible = true;
+ root.certInfoReplaceMode = 5;
+ // "Item Name" text will be set in "onCertificateInfoResult()"
+ // "Edition" text will be set in "onCertificateInfoResult()"
+ // "Owner" text will be set in "onCertificateInfoResult()"
+ // "Purchase Date" text will be set in "onCertificateInfoResult()"
+ // "Purchase Price" text will be set in "onCertificateInfoResult()"
+ errorText.text = "";
+ } else if (root.certificateStatus === 2) { // CERTIFICATE_STATUS_VERIFICATION_TIMEOUT
+ root.useGoldCert = false;
+ root.certTitleTextColor = hifi.colors.redHighlight;
+ root.certTextColor = hifi.colors.redHighlight;
+ root.infoTextColor = hifi.colors.redHighlight;
+ titleBarText.text = "Request Timed Out";
+ popText.text = "";
+ showInMarketplaceButton.visible = false;
+ root.certInfoReplaceMode = 0;
+ root.itemName = "";
+ root.itemEdition = "";
+ root.itemOwner = "";
+ root.dateOfPurchase = "";
+ root.itemCost = "";
+ errorText.text = "Your request to inspect this item timed out. Please try again later.";
+ } else if (root.certificateStatus === 3) { // CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED
+ root.useGoldCert = false;
+ root.certTitleTextColor = hifi.colors.redHighlight;
+ root.certTextColor = hifi.colors.redHighlight;
+ root.infoTextColor = hifi.colors.redHighlight;
+ titleBarText.text = "Certificate\nNo Longer Valid";
+ popText.text = "";
+ showInMarketplaceButton.visible = true;
+ root.certInfoReplaceMode = 5;
+ // "Item Name" text will be set in "onCertificateInfoResult()"
+ // "Edition" text will be set in "onCertificateInfoResult()"
+ // "Owner" text will be set in "onCertificateInfoResult()"
+ // "Purchase Date" text will be set in "onCertificateInfoResult()"
+ // "Purchase Price" text will be set in "onCertificateInfoResult()"
+ errorText.text = "The information associated with this item has been modified and it no longer matches the original certified item.";
+ } else if (root.certificateStatus === 4) { // CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED
+ root.useGoldCert = false;
+ root.certTitleTextColor = hifi.colors.redHighlight;
+ root.certTextColor = hifi.colors.redHighlight;
+ root.infoTextColor = hifi.colors.redHighlight;
+ titleBarText.text = "Invalid Certificate";
+ popText.text = "";
+ showInMarketplaceButton.visible = true;
+ root.certInfoReplaceMode = 4;
+ // "Item Name" text will be set in "onCertificateInfoResult()"
+ root.itemEdition = "Uncertified Copy"
+ // "Owner" text will be set in "onCertificateInfoResult()"
+ // "Purchase Date" text will be set in "onCertificateInfoResult()"
+ // "Purchase Price" text will be set in "onCertificateInfoResult()"
+ // "Error Text" text will be set in "onCertificateInfoResult()"
+ } else {
+ console.log("Unknown certificate status received from ledger signal!");
}
+
+ root.certificateStatusPending = false;
+ // We've gotten cert status - we are GO on getting the cert info
+ Commerce.certificateInfo(root.certificateId);
}
// This object is always used in a popup.
@@ -122,9 +195,35 @@ Rectangle {
hoverEnabled: true;
}
- Image {
+ Rectangle {
+ id: loadingOverlay;
+ z: 998;
+
+ visible: root.certificateInfoPending || root.certificateStatusPending;
anchors.fill: parent;
- source: "images/cert-bg.jpg";
+ color: Qt.rgba(0.0, 0.0, 0.0, 0.7);
+
+ // This object is always used in a popup or full-screen Wallet section.
+ // This MouseArea is used to prevent a user from being
+ // able to click on a button/mouseArea underneath the popup/section.
+ MouseArea {
+ anchors.fill: parent;
+ propagateComposedEvents: false;
+ }
+
+ AnimatedImage {
+ source: "../common/images/loader.gif"
+ width: 96;
+ height: width;
+ anchors.verticalCenter: parent.verticalCenter;
+ anchors.horizontalCenter: parent.horizontalCenter;
+ }
+ }
+
+ Image {
+ id: backgroundImage;
+ anchors.fill: parent;
+ source: root.useGoldCert ? "images/cert-bg-gold-split.png" : "images/nocert-bg-split.png";
}
// Title text
@@ -137,16 +236,17 @@ Rectangle {
anchors.top: parent.top;
anchors.topMargin: 40;
anchors.left: parent.left;
- anchors.leftMargin: 45;
+ anchors.leftMargin: 36;
anchors.right: parent.right;
+ anchors.rightMargin: 8;
height: paintedHeight;
// Style
- color: hifi.colors.darkGray;
+ color: root.certTitleTextColor;
+ wrapMode: Text.WordWrap;
}
// Title text
RalewayRegular {
id: popText;
- text: "Proof of Provenance";
// Text size
size: 16;
// Anchors
@@ -154,9 +254,39 @@ Rectangle {
anchors.topMargin: 4;
anchors.left: titleBarText.left;
anchors.right: titleBarText.right;
- height: paintedHeight;
+ height: text === "" ? 0 : paintedHeight;
// Style
- color: hifi.colors.darkGray;
+ color: root.certTitleTextColor;
+ }
+
+ // "Close" button
+ HiFiGlyphs {
+ z: 999;
+ id: closeGlyphButton;
+ text: hifi.glyphs.close;
+ color: hifi.colors.white;
+ size: 26;
+ anchors.top: parent.top;
+ anchors.topMargin: 10;
+ anchors.right: parent.right;
+ anchors.rightMargin: 10;
+ MouseArea {
+ anchors.fill: parent;
+ hoverEnabled: true;
+ onEntered: {
+ parent.text = hifi.glyphs.closeInverted;
+ }
+ onExited: {
+ parent.text = hifi.glyphs.close;
+ }
+ onClicked: {
+ if (root.isLightbox) {
+ root.visible = false;
+ } else {
+ sendToScript({method: 'inspectionCertificate_closeClicked', closeGoesToPurchases: root.closeGoesToPurchases});
+ }
+ }
+ }
}
//
@@ -164,11 +294,13 @@ Rectangle {
//
Item {
id: certificateContainer;
- anchors.top: popText.bottom;
- anchors.topMargin: 30;
- anchors.bottom: buttonsContainer.top;
+ anchors.top: titleBarText.top;
+ anchors.topMargin: 110;
+ anchors.bottom: infoContainer.top;
anchors.left: parent.left;
+ anchors.leftMargin: titleBarText.anchors.leftMargin;
anchors.right: parent.right;
+ anchors.rightMargin: 24;
RalewayRegular {
id: itemNameHeader;
@@ -178,9 +310,7 @@ Rectangle {
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
- anchors.leftMargin: 45;
anchors.right: parent.right;
- anchors.rightMargin: 16;
height: paintedHeight;
// Style
color: hifi.colors.darkGray;
@@ -197,79 +327,30 @@ Rectangle {
anchors.right: itemNameHeader.right;
height: paintedHeight;
// Style
- color: hifi.colors.white;
+ color: root.certTextColor;
elide: Text.ElideRight;
MouseArea {
+ enabled: showInMarketplaceButton.visible;
anchors.fill: parent;
hoverEnabled: enabled;
onClicked: {
sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', marketplaceUrl: root.marketplaceUrl});
}
onEntered: itemName.color = hifi.colors.blueHighlight;
- onExited: itemName.color = hifi.colors.white;
+ onExited: itemName.color = root.certTextColor;
}
}
- RalewayRegular {
- id: ownedByHeader;
- text: "OWNER";
- // Text size
- size: 16;
- // Anchors
- anchors.top: itemName.bottom;
- anchors.topMargin: 28;
- anchors.left: parent.left;
- anchors.leftMargin: 45;
- anchors.right: parent.right;
- anchors.rightMargin: 16;
- height: paintedHeight;
- // Style
- color: hifi.colors.darkGray;
- }
- RalewayRegular {
- id: ownedBy;
- text: root.itemOwner;
- // Text size
- size: 22;
- // Anchors
- anchors.top: ownedByHeader.bottom;
- anchors.topMargin: 8;
- anchors.left: ownedByHeader.left;
- height: paintedHeight;
- // Style
- color: hifi.colors.white;
- elide: Text.ElideRight;
- }
- AnonymousProRegular {
- id: isMyCertText;
- visible: root.isMyCert && !root.isCertificateInvalid;
- text: "(Private)";
- size: 18;
- // Anchors
- anchors.top: ownedBy.top;
- anchors.topMargin: 4;
- anchors.bottom: ownedBy.bottom;
- anchors.left: ownedBy.right;
- anchors.leftMargin: 6;
- anchors.right: ownedByHeader.right;
- // Style
- color: hifi.colors.white;
- elide: Text.ElideRight;
- verticalAlignment: Text.AlignVCenter;
- }
-
RalewayRegular {
id: editionHeader;
text: "EDITION";
// Text size
size: 16;
// Anchors
- anchors.top: ownedBy.bottom;
+ anchors.top: itemName.bottom;
anchors.topMargin: 28;
anchors.left: parent.left;
- anchors.leftMargin: 45;
anchors.right: parent.right;
- anchors.rightMargin: 16;
height: paintedHeight;
// Style
color: hifi.colors.darkGray;
@@ -286,21 +367,117 @@ Rectangle {
anchors.right: editionHeader.right;
height: paintedHeight;
// Style
- color: hifi.colors.white;
+ color: root.certTextColor;
+ }
+
+ // "Show In Marketplace" button
+ HifiControlsUit.Button {
+ id: showInMarketplaceButton;
+ enabled: root.marketplaceUrl;
+ color: hifi.buttons.blue;
+ colorScheme: hifi.colorSchemes.light;
+ anchors.bottom: parent.bottom;
+ anchors.bottomMargin: 48;
+ anchors.right: parent.right;
+ width: 200;
+ height: 40;
+ text: "View In Market"
+ onClicked: {
+ sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', marketplaceUrl: root.marketplaceUrl});
+ }
+ }
+ }
+ //
+ // "CERTIFICATE" END
+ //
+
+ //
+ // "INFO CONTAINER" START
+ //
+ Item {
+ id: infoContainer;
+ anchors.bottom: parent.bottom;
+ anchors.left: parent.left;
+ anchors.leftMargin: titleBarText.anchors.leftMargin;
+ anchors.right: parent.right;
+ anchors.rightMargin: 24;
+ height: root.useGoldCert ? 220 : 372;
+
+ RalewayRegular {
+ id: errorText;
+ visible: !root.useGoldCert;
+ // Text size
+ size: 20;
+ // Anchors
+ anchors.top: parent.top;
+ anchors.topMargin: 36;
+ anchors.left: parent.left;
+ anchors.right: parent.right;
+ height: 116;
+ // Style
+ wrapMode: Text.WordWrap;
+ color: hifi.colors.baseGray;
+ verticalAlignment: Text.AlignTop;
+ }
+
+ RalewayRegular {
+ id: ownedByHeader;
+ text: "OWNER";
+ // Text size
+ size: 16;
+ // Anchors
+ anchors.top: errorText.visible ? errorText.bottom : parent.top;
+ anchors.topMargin: 28;
+ anchors.left: parent.left;
+ anchors.right: parent.right;
+ height: paintedHeight;
+ // Style
+ color: hifi.colors.darkGray;
+ }
+
+ RalewayRegular {
+ id: ownedBy;
+ text: root.itemOwner;
+ // Text size
+ size: 22;
+ // Anchors
+ anchors.top: ownedByHeader.bottom;
+ anchors.topMargin: 8;
+ anchors.left: ownedByHeader.left;
+ height: paintedHeight;
+ // Style
+ color: root.infoTextColor;
+ elide: Text.ElideRight;
+ }
+ AnonymousProRegular {
+ id: isMyCertText;
+ visible: root.isMyCert && ownedBy.text !== "--" && ownedBy.text !== "";
+ text: "(Private)";
+ size: 18;
+ // Anchors
+ anchors.top: ownedBy.top;
+ anchors.topMargin: 4;
+ anchors.bottom: ownedBy.bottom;
+ anchors.left: ownedBy.right;
+ anchors.leftMargin: 6;
+ anchors.right: ownedByHeader.right;
+ // Style
+ color: root.infoTextColor;
+ elide: Text.ElideRight;
+ verticalAlignment: Text.AlignVCenter;
}
RalewayRegular {
id: dateOfPurchaseHeader;
- text: "DATE OF PURCHASE";
+ text: "PURCHASE DATE";
// Text size
size: 16;
// Anchors
- anchors.top: edition.bottom;
+ anchors.top: ownedBy.bottom;
anchors.topMargin: 28;
anchors.left: parent.left;
- anchors.leftMargin: 45;
- anchors.right: parent.right;
- anchors.rightMargin: 16;
+ anchors.right: parent.horizontalCenter;
+ anchors.rightMargin: 8;
height: paintedHeight;
// Style
color: hifi.colors.darkGray;
@@ -317,73 +494,58 @@ Rectangle {
anchors.right: dateOfPurchaseHeader.right;
height: paintedHeight;
// Style
- color: hifi.colors.white;
+ color: root.infoTextColor;
}
RalewayRegular {
- id: errorText;
+ id: priceHeader;
+ text: "PURCHASE PRICE";
// Text size
- size: 20;
+ size: 16;
// Anchors
- anchors.top: dateOfPurchase.bottom;
- anchors.topMargin: 36;
- anchors.left: dateOfPurchase.left;
- anchors.right: dateOfPurchase.right;
- anchors.bottom: parent.bottom;
- // Style
- wrapMode: Text.WordWrap;
- color: hifi.colors.redHighlight;
- verticalAlignment: Text.AlignTop;
- }
- }
- //
- // "CERTIFICATE" END
- //
-
- Item {
- id: buttonsContainer;
- anchors.bottom: parent.bottom;
- anchors.bottomMargin: 30;
- anchors.left: parent.left;
- anchors.right: parent.right;
- height: 50;
-
- // "Cancel" button
- HifiControlsUit.Button {
- color: hifi.buttons.noneBorderlessWhite;
- colorScheme: hifi.colorSchemes.light;
- anchors.top: parent.top;
- anchors.left: parent.left;
- anchors.leftMargin: 30;
- width: parent.width/2 - 50;
- height: 50;
- text: "close";
- onClicked: {
- if (root.isLightbox) {
- root.visible = false;
- } else {
- sendToScript({method: 'inspectionCertificate_closeClicked', closeGoesToPurchases: root.closeGoesToPurchases});
- }
- }
- }
-
- // "Show In Marketplace" button
- HifiControlsUit.Button {
- id: showInMarketplaceButton;
- enabled: root.marketplaceUrl;
- color: hifi.buttons.blue;
- colorScheme: hifi.colorSchemes.light;
- anchors.top: parent.top;
+ anchors.top: ownedBy.bottom;
+ anchors.topMargin: 28;
+ anchors.left: parent.horizontalCenter;
anchors.right: parent.right;
- anchors.rightMargin: 30;
- width: parent.width/2 - 50;
- height: 50;
- text: "View In Market"
- onClicked: {
- sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', marketplaceUrl: root.marketplaceUrl});
- }
+ height: paintedHeight;
+ // Style
+ color: hifi.colors.darkGray;
+ }
+ HiFiGlyphs {
+ id: hfcGlyph;
+ visible: priceText.text !== "Undisclosed" && priceText.text !== "";
+ text: hifi.glyphs.hfc;
+ // Size
+ size: 24;
+ // Anchors
+ anchors.top: priceHeader.bottom;
+ anchors.topMargin: 8;
+ anchors.left: priceHeader.left;
+ width: visible ? paintedWidth + 6 : 0;
+ height: 40;
+ // Style
+ color: root.infoTextColor;
+ verticalAlignment: Text.AlignTop;
+ horizontalAlignment: Text.AlignLeft;
+ }
+ AnonymousProRegular {
+ id: priceText;
+ text: root.itemCost;
+ // Text size
+ size: 18;
+ // Anchors
+ anchors.top: priceHeader.bottom;
+ anchors.topMargin: 8;
+ anchors.left: hfcGlyph.right;
+ anchors.right: priceHeader.right;
+ height: paintedHeight;
+ // Style
+ color: root.infoTextColor;
}
}
+ //
+ // "INFO CONTAINER" END
+ //
//
// FUNCTION DEFINITIONS START
@@ -404,19 +566,17 @@ Rectangle {
function fromScript(message) {
switch (message.method) {
case 'inspectionCertificate_setCertificateId':
+ resetCert(false);
root.certificateId = message.certificateId;
+ if (message.entityId === "") {
+ updateCertificateStatus(1); // CERTIFICATE_STATUS_VERIFICATION_SUCCESS
+ } else {
+ root.entityId = message.entityId;
+ sendToScript({method: 'inspectionCertificate_requestOwnershipVerification', entity: root.entityId});
+ }
break;
case 'inspectionCertificate_resetCert':
- titleBarText.text = "Certificate";
- popText.text = "PROOF OF PURCHASE";
- root.certificateId = "";
- root.itemName = "--";
- root.itemOwner = "--";
- root.itemEdition = "--";
- root.dateOfPurchase = "--";
- root.marketplaceUrl = "";
- root.isMyCert = false;
- errorText.text = "";
+ resetCert(true);
break;
default:
console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message));
@@ -424,7 +584,34 @@ Rectangle {
}
signal sendToScript(var message);
+ function resetCert(alsoResetCertID) {
+ if (alsoResetCertID) {
+ root.entityId = "";
+ root.certificateId = "";
+ }
+ root.certInfoReplaceMode = 5;
+ root.certificateInfoPending = true;
+ root.certificateStatusPending = true;
+ root.useGoldCert = true;
+ root.certTitleTextColor = hifi.colors.darkGray;
+ root.certTextColor = hifi.colors.white;
+ root.infoTextColor = hifi.colors.blueAccent;
+ titleBarText.text = "Certificate";
+ popText.text = "";
+ root.itemName = "--";
+ root.itemOwner = "--";
+ root.itemEdition = "--";
+ root.dateOfPurchase = "--";
+ root.marketplaceUrl = "";
+ root.itemCost = "--";
+ root.isMyCert = false;
+ errorText.text = "";
+ }
+
function getFormattedDate(timestamp) {
+ if (timestamp === "--") {
+ return "--";
+ }
function addLeadingZero(n) {
return n < 10 ? '0' + n : '' + n;
}
@@ -449,7 +636,7 @@ Rectangle {
var min = addLeadingZero(a.getMinutes());
var sec = addLeadingZero(a.getSeconds());
- return year + '-' + month + '-' + day + '
' + drawnHour + ':' + min + amOrPm;
+ return year + '-' + month + '-' + day + ' ' + drawnHour + ':' + min + amOrPm;
}
//
// FUNCTION DEFINITIONS END
diff --git a/interface/resources/qml/hifi/commerce/inspectionCertificate/images/cert-bg-gold-split.png b/interface/resources/qml/hifi/commerce/inspectionCertificate/images/cert-bg-gold-split.png
new file mode 100644
index 0000000000..14a17df0b1
Binary files /dev/null and b/interface/resources/qml/hifi/commerce/inspectionCertificate/images/cert-bg-gold-split.png differ
diff --git a/interface/resources/qml/hifi/commerce/inspectionCertificate/images/cert-bg.jpg b/interface/resources/qml/hifi/commerce/inspectionCertificate/images/cert-bg.jpg
deleted file mode 100644
index b39a55e4e8..0000000000
Binary files a/interface/resources/qml/hifi/commerce/inspectionCertificate/images/cert-bg.jpg and /dev/null differ
diff --git a/interface/resources/qml/hifi/commerce/inspectionCertificate/images/nocert-bg-split.png b/interface/resources/qml/hifi/commerce/inspectionCertificate/images/nocert-bg-split.png
new file mode 100644
index 0000000000..b2f5a49265
Binary files /dev/null and b/interface/resources/qml/hifi/commerce/inspectionCertificate/images/nocert-bg-split.png differ
diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml
index ee1246c0c4..7dd72b904e 100644
--- a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml
@@ -1115,7 +1115,7 @@ Item {
AnimatedImage {
id: sendingMoneyImage;
- source: "./images/loader.gif"
+ source: "../../common/images/loader.gif"
width: 96;
height: width;
anchors.verticalCenter: parent.verticalCenter;
diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/loader.gif b/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/loader.gif
deleted file mode 100644
index 0536bd1884..0000000000
Binary files a/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/loader.gif and /dev/null differ
diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp
index ed7b811fb0..dd05e5c6a8 100644
--- a/interface/src/ui/overlays/ContextOverlayInterface.cpp
+++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp
@@ -274,82 +274,88 @@ void ContextOverlayInterface::requestOwnershipVerification(const QUuid& entityID
auto nodeList = DependencyManager::get();
- if (entityProperties.getClientOnly()) {
- if (entityProperties.verifyStaticCertificateProperties()) {
- SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer);
+ if (entityProperties.verifyStaticCertificateProperties()) {
+ if (entityProperties.getClientOnly()) {
+ SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer);
- if (entityServer) {
- QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
- QNetworkRequest networkRequest;
- networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
- networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
- QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL();
- requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/transfer");
- QJsonObject request;
- request["certificate_id"] = entityProperties.getCertificateID();
- networkRequest.setUrl(requestURL);
+ if (entityServer) {
+ QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
+ QNetworkRequest networkRequest;
+ networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
+ networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
+ QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL();
+ requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/transfer");
+ QJsonObject request;
+ request["certificate_id"] = entityProperties.getCertificateID();
+ networkRequest.setUrl(requestURL);
- QNetworkReply* networkReply = NULL;
- networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson());
+ QNetworkReply* networkReply = NULL;
+ networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson());
- connect(networkReply, &QNetworkReply::finished, [=]() {
- QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object();
- jsonObject = jsonObject["data"].toObject();
+ connect(networkReply, &QNetworkReply::finished, [=]() {
+ QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object();
+ jsonObject = jsonObject["data"].toObject();
- if (networkReply->error() == QNetworkReply::NoError) {
- if (!jsonObject["invalid_reason"].toString().isEmpty()) {
- qCDebug(entities) << "invalid_reason not empty";
- } else if (jsonObject["transfer_status"].toArray().first().toString() == "failed") {
- qCDebug(entities) << "'transfer_status' is 'failed'";
- } else if (jsonObject["transfer_status"].toArray().first().toString() == "pending") {
- qCDebug(entities) << "'transfer_status' is 'pending'";
- } else {
- QString ownerKey = jsonObject["transfer_recipient_key"].toString();
-
- QByteArray certID = entityProperties.getCertificateID().toUtf8();
- QByteArray text = DependencyManager::get()->getTree()->computeNonce(certID, ownerKey);
- QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122();
-
- int certIDByteArraySize = certID.length();
- int textByteArraySize = text.length();
- int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length();
-
- auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest,
- certIDByteArraySize + textByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int),
- true);
- challengeOwnershipPacket->writePrimitive(certIDByteArraySize);
- challengeOwnershipPacket->writePrimitive(textByteArraySize);
- challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize);
- challengeOwnershipPacket->write(certID);
- challengeOwnershipPacket->write(text);
- challengeOwnershipPacket->write(nodeToChallengeByteArray);
- nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer);
-
- // Kickoff a 10-second timeout timer that marks the cert if we don't get an ownership response in time
- if (thread() != QThread::currentThread()) {
- QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer");
- return;
+ if (networkReply->error() == QNetworkReply::NoError) {
+ if (!jsonObject["invalid_reason"].toString().isEmpty()) {
+ qCDebug(entities) << "invalid_reason not empty";
+ } else if (jsonObject["transfer_status"].toArray().first().toString() == "failed") {
+ qCDebug(entities) << "'transfer_status' is 'failed'";
+ } else if (jsonObject["transfer_status"].toArray().first().toString() == "pending") {
+ qCDebug(entities) << "'transfer_status' is 'pending'";
} else {
- startChallengeOwnershipTimer();
- }
- }
- } else {
- qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() <<
- "More info:" << networkReply->readAll();
- }
+ QString ownerKey = jsonObject["transfer_recipient_key"].toString();
- networkReply->deleteLater();
- });
- } else {
- qCWarning(context_overlay) << "Couldn't get Entity Server!";
- }
+ QByteArray certID = entityProperties.getCertificateID().toUtf8();
+ QByteArray text = DependencyManager::get()->getTree()->computeNonce(certID, ownerKey);
+ QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122();
+
+ int certIDByteArraySize = certID.length();
+ int textByteArraySize = text.length();
+ int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length();
+
+ auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest,
+ certIDByteArraySize + textByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int),
+ true);
+ challengeOwnershipPacket->writePrimitive(certIDByteArraySize);
+ challengeOwnershipPacket->writePrimitive(textByteArraySize);
+ challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize);
+ challengeOwnershipPacket->write(certID);
+ challengeOwnershipPacket->write(text);
+ challengeOwnershipPacket->write(nodeToChallengeByteArray);
+ nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer);
+
+ // Kickoff a 10-second timeout timer that marks the cert if we don't get an ownership response in time
+ if (thread() != QThread::currentThread()) {
+ QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer");
+ return;
+ } else {
+ startChallengeOwnershipTimer();
+ }
+ }
+ } else {
+ qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() <<
+ "More info:" << networkReply->readAll();
+ }
+
+ networkReply->deleteLater();
+ });
+ } else {
+ qCWarning(context_overlay) << "Couldn't get Entity Server!";
+ }
} else {
+ // We don't currently verify ownership of entities that aren't Avatar Entities,
+ // so they always pass Ownership Verification. It's necessary to emit this signal
+ // so that the Inspection Certificate can continue its information-grabbing process.
auto ledger = DependencyManager::get();
- _challengeOwnershipTimeoutTimer.stop();
- emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED));
- emit DependencyManager::get()->ownershipVerificationFailed(_lastInspectedEntity);
- qCDebug(context_overlay) << "Entity" << _lastInspectedEntity << "failed static certificate verification!";
+ emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_VERIFICATION_SUCCESS));
}
+ } else {
+ auto ledger = DependencyManager::get();
+ _challengeOwnershipTimeoutTimer.stop();
+ emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED));
+ emit DependencyManager::get()->ownershipVerificationFailed(_lastInspectedEntity);
+ qCDebug(context_overlay) << "Entity" << _lastInspectedEntity << "failed static certificate verification!";
}
}
@@ -357,12 +363,10 @@ static const QString INSPECTION_CERTIFICATE_QML_PATH = "hifi/commerce/inspection
void ContextOverlayInterface::openInspectionCertificate() {
// lets open the tablet to the inspection certificate QML
if (!_currentEntityWithContextOverlay.isNull() && _entityMarketplaceID.length() > 0) {
+ setLastInspectedEntity(_currentEntityWithContextOverlay);
auto tablet = dynamic_cast(_tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
tablet->loadQMLSource(INSPECTION_CERTIFICATE_QML_PATH);
_hmdScriptingInterface->openTablet();
-
- setLastInspectedEntity(_currentEntityWithContextOverlay);
- requestOwnershipVerification(_lastInspectedEntity);
}
}
diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h
index 6aad2a773b..fcdf2d5820 100644
--- a/interface/src/ui/overlays/ContextOverlayInterface.h
+++ b/interface/src/ui/overlays/ContextOverlayInterface.h
@@ -57,7 +57,7 @@ public:
bool getEnabled() { return _enabled; }
bool getIsInMarketplaceInspectionMode() { return _isInMarketplaceInspectionMode; }
void setIsInMarketplaceInspectionMode(bool mode) { _isInMarketplaceInspectionMode = mode; }
- void requestOwnershipVerification(const QUuid& entityID);
+ Q_INVOKABLE void requestOwnershipVerification(const QUuid& entityID);
EntityPropertyFlags getEntityPropertyFlags() { return _entityPropertyFlags; }
signals:
diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js
index edcd488a01..fd1275a251 100644
--- a/scripts/system/marketplaces/marketplaces.js
+++ b/scripts/system/marketplaces/marketplaces.js
@@ -163,6 +163,7 @@ var selectionDisplay = null; // for gridTool.js to ignore
var certificateId = itemCertificateId || (Entities.getEntityProperties(currentEntityWithContextOverlay, ['certificateID']).certificateID);
tablet.sendToQml({
method: 'inspectionCertificate_setCertificateId',
+ entityId: currentEntityWithContextOverlay,
certificateId: certificateId
});
}
@@ -583,6 +584,9 @@ var selectionDisplay = null; // for gridTool.js to ignore
case 'inspectionCertificate_closeClicked':
tablet.gotoHomeScreen();
break;
+ case 'inspectionCertificate_requestOwnershipVerification':
+ ContextOverlay.requestOwnershipVerification(message.entity);
+ break;
case 'inspectionCertificate_showInMarketplaceClicked':
tablet.gotoWebScreen(message.marketplaceUrl, MARKETPLACES_INJECT_SCRIPT_URL);
break;