mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-13 22:27:13 +02:00
Merge pull request #11495 from zfox23/pop_interfaceChanges2
Commerce: One step closer!
This commit is contained in:
commit
ea3da6c9dd
32 changed files with 950 additions and 448 deletions
|
@ -26,72 +26,57 @@ Rectangle {
|
|||
HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
objectName: "checkout"
|
||||
property string activeView: "initialize";
|
||||
property bool purchasesReceived: false;
|
||||
property bool balanceReceived: false;
|
||||
property bool securityImageResultReceived: false;
|
||||
property string itemName;
|
||||
property string itemId;
|
||||
property string itemPreviewImageUrl;
|
||||
property string itemHref;
|
||||
property double balanceAfterPurchase;
|
||||
property bool alreadyOwned: false;
|
||||
property int itemPrice: 0;
|
||||
property int itemPrice;
|
||||
property bool itemIsJson: true;
|
||||
property bool shouldBuyWithControlledFailure: false;
|
||||
property bool debugCheckoutSuccess: false;
|
||||
property bool canRezCertifiedItems: false;
|
||||
property bool canRezCertifiedItems: Entities.canRezCertified || Entities.canRezTmpCertified;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
Hifi.QmlCommerce {
|
||||
id: commerce;
|
||||
|
||||
onWalletStatusResult: {
|
||||
if (walletStatus === 0) {
|
||||
if (root.activeView !== "needsLogIn") {
|
||||
root.activeView = "needsLogIn";
|
||||
}
|
||||
} else if (walletStatus === 1) {
|
||||
if (root.activeView !== "notSetUp") {
|
||||
root.activeView = "notSetUp";
|
||||
notSetUpTimer.start();
|
||||
}
|
||||
} else if (walletStatus === 2) {
|
||||
if (root.activeView !== "passphraseModal") {
|
||||
root.activeView = "passphraseModal";
|
||||
}
|
||||
} else if (walletStatus === 3) {
|
||||
authSuccessStep();
|
||||
} else {
|
||||
console.log("ERROR in Checkout.qml: Unknown wallet status: " + walletStatus);
|
||||
}
|
||||
}
|
||||
|
||||
onLoginStatusResult: {
|
||||
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
||||
root.activeView = "needsLogIn";
|
||||
} else if (isLoggedIn) {
|
||||
root.activeView = "initialize";
|
||||
commerce.account();
|
||||
}
|
||||
}
|
||||
|
||||
onAccountResult: {
|
||||
if (result.status === "success") {
|
||||
commerce.getKeyFilePathIfExists();
|
||||
} else {
|
||||
// unsure how to handle a failure here. We definitely cannot proceed.
|
||||
}
|
||||
}
|
||||
|
||||
onKeyFilePathIfExistsResult: {
|
||||
if (path === "" && root.activeView !== "notSetUp") {
|
||||
root.activeView = "notSetUp";
|
||||
notSetUpTimer.start();
|
||||
} else if (path !== "" && root.activeView === "initialize") {
|
||||
commerce.getSecurityImage();
|
||||
}
|
||||
}
|
||||
|
||||
onSecurityImageResult: {
|
||||
securityImageResultReceived = true;
|
||||
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
|
||||
root.activeView = "notSetUp";
|
||||
notSetUpTimer.start();
|
||||
} else if (exists && root.activeView === "initialize") {
|
||||
commerce.getWalletAuthenticatedStatus();
|
||||
}
|
||||
}
|
||||
|
||||
onWalletAuthenticatedStatusResult: {
|
||||
if (!isAuthenticated && root.activeView !== "passphraseModal") {
|
||||
root.activeView = "passphraseModal";
|
||||
} else if (isAuthenticated) {
|
||||
authSuccessStep();
|
||||
commerce.getWalletStatus();
|
||||
}
|
||||
}
|
||||
|
||||
onBuyResult: {
|
||||
if (result.status !== 'success') {
|
||||
failureErrorText.text = "Here's some more info about the error:<br><br>" + (result.message);
|
||||
failureErrorText.text = result.message;
|
||||
root.activeView = "checkoutFailure";
|
||||
} else {
|
||||
root.activeView = "checkoutSuccess";
|
||||
|
@ -123,6 +108,19 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
onItemIdChanged: {
|
||||
commerce.inventory();
|
||||
itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg";
|
||||
}
|
||||
|
||||
onItemHrefChanged: {
|
||||
itemIsJson = root.itemHref.indexOf('.json') !== -1;
|
||||
}
|
||||
|
||||
onItemPriceChanged: {
|
||||
commerce.balance();
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: notSetUpTimer;
|
||||
interval: 200;
|
||||
|
@ -176,6 +174,13 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
enabled: titleBarContainer.usernameDropdownVisible;
|
||||
anchors.fill: parent;
|
||||
onClicked: {
|
||||
titleBarContainer.usernameDropdownVisible = false;
|
||||
}
|
||||
}
|
||||
//
|
||||
// TITLE BAR END
|
||||
//
|
||||
|
@ -190,10 +195,9 @@ Rectangle {
|
|||
color: hifi.colors.white;
|
||||
|
||||
Component.onCompleted: {
|
||||
securityImageResultReceived = false;
|
||||
purchasesReceived = false;
|
||||
balanceReceived = false;
|
||||
commerce.getLoginStatus();
|
||||
commerce.getWalletStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,7 +285,6 @@ Rectangle {
|
|||
|
||||
Image {
|
||||
id: itemPreviewImage;
|
||||
source: root.itemPreviewImageUrl;
|
||||
anchors.left: parent.left;
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
|
@ -291,6 +294,7 @@ Rectangle {
|
|||
|
||||
RalewaySemiBold {
|
||||
id: itemNameText;
|
||||
text: root.itemName;
|
||||
// Text size
|
||||
size: 26;
|
||||
// Anchors
|
||||
|
@ -315,19 +319,19 @@ Rectangle {
|
|||
anchors.top: parent.top;
|
||||
anchors.right: parent.right;
|
||||
height: 30;
|
||||
width: childrenRect.width;
|
||||
width: itemPriceTextLabel.width + itemPriceText.width + 20;
|
||||
|
||||
// "HFC" balance label
|
||||
HiFiGlyphs {
|
||||
id: itemPriceTextLabel;
|
||||
text: hifi.glyphs.hfc;
|
||||
// Size
|
||||
size: 36;
|
||||
size: 30;
|
||||
// Anchors
|
||||
anchors.right: itemPriceText.left;
|
||||
anchors.rightMargin: 4;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: -4;
|
||||
anchors.topMargin: 0;
|
||||
width: paintedWidth;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
|
@ -335,7 +339,7 @@ Rectangle {
|
|||
}
|
||||
FiraSansSemiBold {
|
||||
id: itemPriceText;
|
||||
text: "--";
|
||||
text: root.itemPrice;
|
||||
// Text size
|
||||
size: 26;
|
||||
// Anchors
|
||||
|
@ -405,7 +409,7 @@ Rectangle {
|
|||
verticalAlignment: Text.AlignTop;
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
RalewayRegular {
|
||||
id: buyText;
|
||||
// Text size
|
||||
size: 18;
|
||||
|
@ -424,7 +428,7 @@ Rectangle {
|
|||
verticalAlignment: Text.AlignVCenter;
|
||||
|
||||
onLinkActivated: {
|
||||
sendToScript({method: 'checkout_goToPurchases', filterText: itemNameText.text});
|
||||
sendToScript({method: 'checkout_goToPurchases', filterText: root.itemName});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -508,7 +512,7 @@ Rectangle {
|
|||
|
||||
RalewaySemiBold {
|
||||
id: completeText2;
|
||||
text: "The item " + '<font color="' + hifi.colors.blueAccent + '"><a href="#">' + itemNameText.text + '</a></font>' +
|
||||
text: "The item " + '<font color="' + hifi.colors.blueAccent + '"><a href="#">' + root.itemName + '</a></font>' +
|
||||
" has been added to your Purchases and a receipt will appear in your Wallet's transaction history.";
|
||||
// Text size
|
||||
size: 20;
|
||||
|
@ -709,7 +713,9 @@ Rectangle {
|
|||
anchors.top: titleBarContainer.bottom;
|
||||
anchors.bottom: root.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 16;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 16;
|
||||
|
||||
RalewayRegular {
|
||||
id: failureHeaderText;
|
||||
|
@ -718,57 +724,65 @@ Rectangle {
|
|||
size: 24;
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 80;
|
||||
anchors.topMargin: 40;
|
||||
height: paintedHeight;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
// Style
|
||||
color: hifi.colors.black;
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
|
||||
RalewayRegular {
|
||||
id: failureErrorText;
|
||||
// Text size
|
||||
size: 16;
|
||||
// Anchors
|
||||
Rectangle {
|
||||
id: failureErrorTextContainer;
|
||||
anchors.top: failureHeaderText.bottom;
|
||||
anchors.topMargin: 35;
|
||||
height: paintedHeight;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
// Style
|
||||
color: hifi.colors.black;
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
height: failureErrorText.height + 30;
|
||||
radius: 4;
|
||||
border.width: 2;
|
||||
border.color: "#F3808F";
|
||||
color: "#FFC3CD";
|
||||
|
||||
AnonymousProRegular {
|
||||
id: failureErrorText;
|
||||
// Text size
|
||||
size: 16;
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 15;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 8;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 8;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.black;
|
||||
wrapMode: Text.Wrap;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: backToMarketplaceButtonContainer;
|
||||
// Size
|
||||
width: root.width;
|
||||
height: 130;
|
||||
height: 50;
|
||||
// Anchors
|
||||
anchors.left: parent.left;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.bottomMargin: 8;
|
||||
anchors.bottomMargin: 16;
|
||||
// "Back to Marketplace" button
|
||||
HifiControlsUit.Button {
|
||||
id: backToMarketplaceButton;
|
||||
color: hifi.buttons.black;
|
||||
color: hifi.buttons.noneBorderlessGray;
|
||||
colorScheme: hifi.colorSchemes.light;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 3;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.bottomMargin: 3;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 20;
|
||||
width: parent.width/2 - anchors.rightMargin*2;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 16;
|
||||
width: parent.width/2 - anchors.leftMargin*2;
|
||||
text: "Back to Marketplace";
|
||||
onClicked: {
|
||||
sendToScript({method: 'checkout_continueShopping', itemId: itemId});
|
||||
|
@ -814,15 +828,9 @@ Rectangle {
|
|||
switch (message.method) {
|
||||
case 'updateCheckoutQML':
|
||||
itemId = message.params.itemId;
|
||||
itemNameText.text = message.params.itemName;
|
||||
itemName = message.params.itemName;
|
||||
root.itemPrice = message.params.itemPrice;
|
||||
itemPriceText.text = root.itemPrice === 0 ? "Free" : root.itemPrice;
|
||||
itemHref = message.params.itemHref;
|
||||
itemPreviewImageUrl = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg";
|
||||
if (itemHref.indexOf('.json') === -1) {
|
||||
root.itemIsJson = false;
|
||||
}
|
||||
root.canRezCertifiedItems = message.canRezCertifiedItems;
|
||||
setBuyText();
|
||||
break;
|
||||
default:
|
||||
|
@ -845,10 +853,10 @@ Rectangle {
|
|||
if (root.purchasesReceived && root.balanceReceived) {
|
||||
if (root.balanceAfterPurchase < 0) {
|
||||
if (root.alreadyOwned) {
|
||||
buyText.text = "Your Wallet does not have sufficient funds to purchase this item again.<br>" +
|
||||
'<font color="' + hifi.colors.blueAccent + '"><a href="#">View the copy you own in My Purchases</a></font>';
|
||||
buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item again.<br>" +
|
||||
'<font color="' + hifi.colors.blueAccent + '"><a href="#">View the copy you own in My Purchases</a></font></b>';
|
||||
} else {
|
||||
buyText.text = "Your Wallet does not have sufficient funds to purchase this item.";
|
||||
buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item.</b>";
|
||||
}
|
||||
buyTextContainer.color = "#FFC3CD";
|
||||
buyTextContainer.border.color = "#F3808F";
|
||||
|
@ -856,8 +864,8 @@ Rectangle {
|
|||
buyGlyph.size = 54;
|
||||
} else {
|
||||
if (root.alreadyOwned) {
|
||||
buyText.text = 'You already own this item.<br>Purchasing it will buy another copy.<br><font color="'
|
||||
+ hifi.colors.blueAccent + '"><a href="#">View this item in My Purchases</a></font>';
|
||||
buyText.text = '<b>You already own this item.<br>Purchasing it will buy another copy.<br><font color="'
|
||||
+ hifi.colors.blueAccent + '"><a href="#">View this item in My Purchases</a></font></b>';
|
||||
buyTextContainer.color = "#FFD6AD";
|
||||
buyTextContainer.border.color = "#FAC07D";
|
||||
buyGlyph.text = hifi.glyphs.alert;
|
||||
|
@ -870,7 +878,7 @@ Rectangle {
|
|||
buyText.text = "";
|
||||
}
|
||||
} else {
|
||||
buyText.text = "This Marketplace item isn't an entity. It <b>will not</b> be added to your <b>Purchases</b>.";
|
||||
buyText.text = "This free item <b>will not</b> be added to your <b>Purchases</b>. Non-entities can't yet be purchased for HFC.";
|
||||
buyTextContainer.color = "#FFD6AD";
|
||||
buyTextContainer.border.color = "#FAC07D";
|
||||
buyGlyph.text = hifi.glyphs.alert;
|
||||
|
@ -884,12 +892,6 @@ Rectangle {
|
|||
} else {
|
||||
root.activeView = "checkoutSuccess";
|
||||
}
|
||||
if (!balanceReceived) {
|
||||
commerce.balance();
|
||||
}
|
||||
if (!purchasesReceived) {
|
||||
commerce.inventory();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -82,6 +82,7 @@ Rectangle {
|
|||
height: 140;
|
||||
fillMode: Image.PreserveAspectFit;
|
||||
mipmap: true;
|
||||
cache: false;
|
||||
}
|
||||
|
||||
RalewayRegular {
|
||||
|
|
|
@ -27,23 +27,28 @@ Item {
|
|||
id: root;
|
||||
property string referrerURL: "https://metaverse.highfidelity.com/marketplace?";
|
||||
readonly property int additionalDropdownHeight: usernameDropdown.height - myUsernameButton.anchors.bottomMargin;
|
||||
property alias usernameDropdownVisible: usernameDropdown.visible;
|
||||
|
||||
height: mainContainer.height + additionalDropdownHeight;
|
||||
|
||||
Hifi.QmlCommerce {
|
||||
id: commerce;
|
||||
|
||||
onLoginStatusResult: {
|
||||
if (!isLoggedIn) {
|
||||
onWalletStatusResult: {
|
||||
if (walletStatus === 0) {
|
||||
sendToParent({method: "needsLogIn"});
|
||||
} else if (walletStatus === 3) {
|
||||
commerce.getSecurityImage();
|
||||
} else {
|
||||
console.log("ERROR in EmulatedMarketplaceHeader.qml: Unknown wallet status: " + walletStatus);
|
||||
}
|
||||
}
|
||||
|
||||
onAccountResult: {
|
||||
if (result.status === "success") {
|
||||
commerce.getKeyFilePathIfExists();
|
||||
onLoginStatusResult: {
|
||||
if (!isLoggedIn) {
|
||||
sendToParent({method: "needsLogIn"});
|
||||
} else {
|
||||
// unsure how to handle a failure here. We definitely cannot proceed.
|
||||
commerce.getWalletStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,8 +61,7 @@ Item {
|
|||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
commerce.getLoginStatus();
|
||||
commerce.getSecurityImage();
|
||||
commerce.getWalletStatus();
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
@ -210,6 +214,7 @@ Item {
|
|||
anchors.bottomMargin: 16;
|
||||
width: height;
|
||||
mipmap: true;
|
||||
cache: false;
|
||||
|
||||
MouseArea {
|
||||
enabled: securityImage.visible;
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// SortableListModel.qml
|
||||
// qml/hifi/commerce/common
|
||||
//
|
||||
// SortableListModel
|
||||
//
|
||||
// Created by Zach Fox on 2017-09-28
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
|
||||
ListModel {
|
||||
id: root;
|
||||
property string sortColumnName: "";
|
||||
property bool isSortingDescending: true;
|
||||
|
||||
function swap(a, b) {
|
||||
if (a < b) {
|
||||
move(a, b, 1);
|
||||
move (b - 1, a, 1);
|
||||
} else if (a > b) {
|
||||
move(b, a, 1);
|
||||
move(a - 1, b, 1);
|
||||
}
|
||||
}
|
||||
|
||||
function partition(begin, end, pivot) {
|
||||
var piv = get(pivot)[sortColumnName];
|
||||
swap(pivot, end - 1);
|
||||
var store = begin;
|
||||
|
||||
for (var i = begin; i < end - 1; ++i) {
|
||||
if (isSortingDescending) {
|
||||
if (get(i)[sortColumnName] < piv) {
|
||||
swap(store, i);
|
||||
++store;
|
||||
}
|
||||
} else {
|
||||
if (get(i)[sortColumnName] > piv) {
|
||||
swap(store, i);
|
||||
++store;
|
||||
}
|
||||
}
|
||||
}
|
||||
swap(end - 1, store);
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
function qsort(begin, end) {
|
||||
if (end - 1 > begin) {
|
||||
var pivot = begin + Math.floor(Math.random() * (end - begin));
|
||||
|
||||
pivot = partition(begin, end, pivot);
|
||||
|
||||
qsort(begin, pivot);
|
||||
qsort(pivot + 1, end);
|
||||
}
|
||||
}
|
||||
|
||||
function quickSort() {
|
||||
qsort(0, count)
|
||||
}
|
||||
}
|
|
@ -30,12 +30,20 @@ Rectangle {
|
|||
property string itemOwner: "--";
|
||||
property string itemEdition: "--";
|
||||
property string dateOfPurchase: "";
|
||||
property bool closeGoesToPurchases: false;
|
||||
property bool isLightbox: false;
|
||||
// Style
|
||||
color: hifi.colors.faintGray;
|
||||
Hifi.QmlCommerce {
|
||||
id: commerce;
|
||||
}
|
||||
}
|
||||
|
||||
// This object is always used in a popup.
|
||||
// This MouseArea is used to prevent a user from being
|
||||
// able to click on a button/mouseArea underneath the popup.
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
propagateComposedEvents: false;
|
||||
}
|
||||
|
||||
Image {
|
||||
anchors.fill: parent;
|
||||
|
@ -262,7 +270,11 @@ Rectangle {
|
|||
height: 50;
|
||||
text: "close";
|
||||
onClicked: {
|
||||
sendToScript({method: 'inspectionCertificate_closeClicked', closeGoesToPurchases: root.closeGoesToPurchases});
|
||||
if (root.isLightbox) {
|
||||
root.visible = false;
|
||||
} else {
|
||||
sendToScript({method: 'inspectionCertificate_closeClicked', closeGoesToPurchases: root.closeGoesToPurchases});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,7 +315,6 @@ Rectangle {
|
|||
switch (message.method) {
|
||||
case 'inspectionCertificate_setMarketplaceId':
|
||||
root.marketplaceId = message.marketplaceId;
|
||||
root.closeGoesToPurchases = message.closeGoesToPurchases;
|
||||
break;
|
||||
case 'inspectionCertificate_setItemInfo':
|
||||
root.itemName = message.itemName;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
import Hifi 1.0 as Hifi
|
||||
import QtQuick 2.5
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Controls 1.4
|
||||
import "../../../styles-uit"
|
||||
import "../../../controls-uit" as HifiControlsUit
|
||||
|
@ -24,40 +25,133 @@ Rectangle {
|
|||
HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
property string activeView: "step_1";
|
||||
// Style
|
||||
color: hifi.colors.baseGray;
|
||||
property int activeView: 1;
|
||||
|
||||
Image {
|
||||
anchors.fill: parent;
|
||||
source: "images/Purchase-First-Run-" + root.activeView + ".jpg";
|
||||
}
|
||||
|
||||
// This object is always used in a popup.
|
||||
// This MouseArea is used to prevent a user from being
|
||||
// able to click on a button/mouseArea underneath the popup.
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
propagateComposedEvents: false;
|
||||
}
|
||||
|
||||
Item {
|
||||
id: header;
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
height: childrenRect.height;
|
||||
|
||||
Image {
|
||||
id: marketplaceHeaderImage;
|
||||
source: "../common/images/marketplaceHeaderImage.png";
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 2;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 8;
|
||||
width: 140;
|
||||
height: 58;
|
||||
fillMode: Image.PreserveAspectFit;
|
||||
visible: false;
|
||||
}
|
||||
ColorOverlay {
|
||||
anchors.fill: marketplaceHeaderImage;
|
||||
source: marketplaceHeaderImage;
|
||||
color: "#FFFFFF"
|
||||
}
|
||||
RalewayRegular {
|
||||
id: introText1;
|
||||
text: "INTRODUCTION TO";
|
||||
// Text size
|
||||
size: 15;
|
||||
// Anchors
|
||||
anchors.top: marketplaceHeaderImage.bottom;
|
||||
anchors.topMargin: 8;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 12;
|
||||
anchors.right: parent.right;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
}
|
||||
RalewayRegular {
|
||||
id: introText2;
|
||||
text: "My Purchases";
|
||||
// Text size
|
||||
size: 28;
|
||||
// Anchors
|
||||
anchors.top: introText1.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 12;
|
||||
anchors.right: parent.right;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// "STEP 1" START
|
||||
//
|
||||
Item {
|
||||
id: step_1;
|
||||
visible: root.activeView === "step_1";
|
||||
anchors.top: parent.top;
|
||||
visible: root.activeView === 1;
|
||||
anchors.top: header.bottom;
|
||||
anchors.topMargin: 100;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 30;
|
||||
anchors.right: parent.right;
|
||||
anchors.bottom: tutorialActionButtonsContainer.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
|
||||
RalewayRegular {
|
||||
id: step1text;
|
||||
text: "<b>This is the first-time Purchases tutorial.</b><br><br>Here is some <b>bold text</b> " +
|
||||
"inside Step 1.";
|
||||
text: "The <b>'REZ IT'</b> button makes your purchase appear in front of you.";
|
||||
// Text size
|
||||
size: 24;
|
||||
size: 20;
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 16;
|
||||
width: 180;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
wrapMode: Text.WordWrap;
|
||||
}
|
||||
|
||||
// "Next" button
|
||||
HifiControlsUit.Button {
|
||||
color: hifi.buttons.blue;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: step1text.bottom;
|
||||
anchors.topMargin: 16;
|
||||
anchors.left: parent.left;
|
||||
width: 150;
|
||||
height: 40;
|
||||
text: "Next";
|
||||
onClicked: {
|
||||
root.activeView++;
|
||||
}
|
||||
}
|
||||
|
||||
// "SKIP" button
|
||||
HifiControlsUit.Button {
|
||||
color: hifi.buttons.noneBorderlessGray;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.bottomMargin: 32;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 16;
|
||||
// Style
|
||||
color: hifi.colors.faintGray;
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
width: 150;
|
||||
height: 40;
|
||||
text: "SKIP";
|
||||
onClicked: {
|
||||
sendSignalToParent({method: 'tutorial_finished'});
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
|
@ -69,127 +163,52 @@ Rectangle {
|
|||
//
|
||||
Item {
|
||||
id: step_2;
|
||||
visible: root.activeView === "step_2";
|
||||
anchors.top: parent.top;
|
||||
visible: root.activeView === 2;
|
||||
anchors.top: header.bottom;
|
||||
anchors.topMargin: 45;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 30;
|
||||
anchors.right: parent.right;
|
||||
anchors.bottom: tutorialActionButtonsContainer.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
|
||||
RalewayRegular {
|
||||
id: step2text;
|
||||
text: "<b>STEP TWOOO!!!</b>";
|
||||
text: "If you rez an item twice, the first one will disappear.";
|
||||
// Text size
|
||||
size: 24;
|
||||
size: 20;
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 16;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 16;
|
||||
width: 180;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.faintGray;
|
||||
color: hifi.colors.white;
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
|
||||
// "GOT IT" button
|
||||
HifiControlsUit.Button {
|
||||
color: hifi.buttons.blue;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: step2text.bottom;
|
||||
anchors.topMargin: 16;
|
||||
anchors.left: parent.left;
|
||||
width: 150;
|
||||
height: 40;
|
||||
text: "GOT IT";
|
||||
onClicked: {
|
||||
sendSignalToParent({method: 'tutorial_finished'});
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// "STEP 2" END
|
||||
//
|
||||
|
||||
Item {
|
||||
id: tutorialActionButtonsContainer;
|
||||
// Size
|
||||
width: root.width;
|
||||
height: 70;
|
||||
// Anchors
|
||||
anchors.left: parent.left;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.bottomMargin: 24;
|
||||
|
||||
// "Skip" or "Back" button
|
||||
HifiControlsUit.Button {
|
||||
id: skipOrBackButton;
|
||||
color: hifi.buttons.black;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 3;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.bottomMargin: 3;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 20;
|
||||
width: parent.width/2 - anchors.leftMargin*2;
|
||||
text: root.activeView === "step_1" ? "Skip" : "Back";
|
||||
onClicked: {
|
||||
if (root.activeView === "step_1") {
|
||||
sendSignalToParent({method: 'tutorial_skipClicked'});
|
||||
} else {
|
||||
root.activeView = "step_" + (parseInt(root.activeView.split("_")[1]) - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "Next" or "Finish" button
|
||||
HifiControlsUit.Button {
|
||||
id: nextButton;
|
||||
color: hifi.buttons.blue;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 3;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.bottomMargin: 3;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 20;
|
||||
width: parent.width/2 - anchors.rightMargin*2;
|
||||
text: root.activeView === "step_2" ? "Finish" : "Next";
|
||||
onClicked: {
|
||||
// If this is the final step...
|
||||
if (root.activeView === "step_2") {
|
||||
sendSignalToParent({method: 'tutorial_finished'});
|
||||
} else {
|
||||
root.activeView = "step_" + (parseInt(root.activeView.split("_")[1]) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// FUNCTION DEFINITIONS START
|
||||
//
|
||||
//
|
||||
// Function Name: fromScript()
|
||||
//
|
||||
// Relevant Variables:
|
||||
// None
|
||||
//
|
||||
// Arguments:
|
||||
// message: The message sent from the JavaScript, in this case the Marketplaces JavaScript.
|
||||
// Messages are in format "{method, params}", like json-rpc.
|
||||
//
|
||||
// Description:
|
||||
// Called when a message is received from a script.
|
||||
//
|
||||
function fromScript(message) {
|
||||
switch (message.method) {
|
||||
case 'updatePurchases':
|
||||
referrerURL = message.referrerURL;
|
||||
break;
|
||||
case 'purchases_getIsFirstUseResult':
|
||||
if (message.isFirstUseOfPurchases && root.activeView !== "firstUseTutorial") {
|
||||
root.activeView = "firstUseTutorial";
|
||||
} else if (!message.isFirstUseOfPurchases && root.activeView === "initialize") {
|
||||
root.activeView = "purchasesMain";
|
||||
commerce.inventory();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message));
|
||||
}
|
||||
}
|
||||
signal sendSignalToParent(var message);
|
||||
|
||||
//
|
||||
// FUNCTION DEFINITIONS END
|
||||
//
|
||||
|
|
|
@ -34,14 +34,19 @@ Item {
|
|||
property string itemId;
|
||||
property string itemPreviewImageUrl;
|
||||
property string itemHref;
|
||||
property int ownedItemCount;
|
||||
property int displayedItemCount;
|
||||
property int itemEdition;
|
||||
|
||||
property string originalStatusText;
|
||||
property string originalStatusColor;
|
||||
|
||||
height: 110;
|
||||
width: parent.width;
|
||||
|
||||
onPurchaseStatusChangedChanged: {
|
||||
if (root.purchaseStatusChanged === true && root.purchaseStatus === "confirmed") {
|
||||
root.originalStatusText = statusText.text;
|
||||
root.originalStatusColor = statusText.color;
|
||||
statusText.text = "CONFIRMED!";
|
||||
statusText.color = hifi.colors.blueAccent;
|
||||
confirmedTimer.start();
|
||||
|
@ -53,7 +58,8 @@ Item {
|
|||
id: confirmedTimer;
|
||||
interval: 3000;
|
||||
onTriggered: {
|
||||
root.purchaseStatus = "";
|
||||
statusText.text = root.originalStatusText;
|
||||
statusText.color = root.originalStatusColor;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,9 +180,30 @@ Item {
|
|||
}
|
||||
|
||||
Item {
|
||||
id: statusContainer;
|
||||
id: editionContainer;
|
||||
visible: root.displayedItemCount > 1 && !statusContainer.visible;
|
||||
anchors.left: itemName.left;
|
||||
anchors.top: certificateContainer.bottom;
|
||||
anchors.topMargin: 8;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.right: buttonContainer.left;
|
||||
anchors.rightMargin: 2;
|
||||
|
||||
visible: root.purchaseStatus || root.ownedItemCount > 1;
|
||||
FiraSansRegular {
|
||||
anchors.left: parent.left;
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
width: paintedWidth;
|
||||
text: "#" + root.itemEdition;
|
||||
size: 15;
|
||||
color: "#cc6a6a6a";
|
||||
verticalAlignment: Text.AlignTop;
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: statusContainer;
|
||||
visible: root.purchaseStatus === "pending" || root.purchaseStatus === "invalidated";
|
||||
anchors.left: itemName.left;
|
||||
anchors.top: certificateContainer.bottom;
|
||||
anchors.topMargin: 8;
|
||||
|
@ -195,8 +222,6 @@ Item {
|
|||
"PENDING..."
|
||||
} else if (root.purchaseStatus === "invalidated") {
|
||||
"INVALIDATED"
|
||||
} else if (root.ownedItemCount > 1) {
|
||||
"<font color='#6a6a6a'>(#" + root.itemEdition + ")</font> <u>You own " + root.ownedItemCount + " others</u>"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
@ -207,8 +232,6 @@ Item {
|
|||
hifi.colors.blueAccent
|
||||
} else if (root.purchaseStatus === "invalidated") {
|
||||
hifi.colors.redAccent
|
||||
} else if (root.ownedItemCount > 1) {
|
||||
hifi.colors.blueAccent
|
||||
} else {
|
||||
hifi.colors.baseGray
|
||||
}
|
||||
|
@ -240,8 +263,6 @@ Item {
|
|||
hifi.colors.blueAccent
|
||||
} else if (root.purchaseStatus === "invalidated") {
|
||||
hifi.colors.redAccent
|
||||
} else if (root.ownedItemCount > 1) {
|
||||
hifi.colors.blueAccent
|
||||
} else {
|
||||
hifi.colors.baseGray
|
||||
}
|
||||
|
@ -257,8 +278,6 @@ Item {
|
|||
sendToPurchases({method: 'showPendingLightbox'});
|
||||
} else if (root.purchaseStatus === "invalidated") {
|
||||
sendToPurchases({method: 'showInvalidatedLightbox'});
|
||||
} else if (root.ownedItemCount > 1) {
|
||||
sendToPurchases({method: 'setFilterText', filterText: root.itemName});
|
||||
}
|
||||
}
|
||||
onEntered: {
|
||||
|
@ -268,9 +287,6 @@ Item {
|
|||
} else if (root.purchaseStatus === "invalidated") {
|
||||
statusText.color = hifi.colors.redAccent;
|
||||
statusIcon.color = hifi.colors.redAccent;
|
||||
} else if (root.ownedItemCount > 1) {
|
||||
statusText.color = hifi.colors.blueHighlight;
|
||||
statusIcon.color = hifi.colors.blueHighlight;
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
|
@ -280,9 +296,6 @@ Item {
|
|||
} else if (root.purchaseStatus === "invalidated") {
|
||||
statusText.color = hifi.colors.redHighlight;
|
||||
statusIcon.color = hifi.colors.redHighlight;
|
||||
} else if (root.ownedItemCount > 1) {
|
||||
statusText.color = hifi.colors.blueAccent;
|
||||
statusIcon.color = hifi.colors.blueAccent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import "../../../controls-uit" as HifiControlsUit
|
|||
import "../../../controls" as HifiControls
|
||||
import "../wallet" as HifiWallet
|
||||
import "../common" as HifiCommerceCommon
|
||||
import "../inspectionCertificate" as HifiInspectionCertificate
|
||||
|
||||
// references XXX from root context
|
||||
|
||||
|
@ -31,54 +32,46 @@ Rectangle {
|
|||
property bool securityImageResultReceived: false;
|
||||
property bool purchasesReceived: false;
|
||||
property bool punctuationMode: false;
|
||||
property bool canRezCertifiedItems: false;
|
||||
property bool canRezCertifiedItems: Entities.canRezCertified || Entities.canRezTmpCertified;
|
||||
property bool pendingInventoryReply: true;
|
||||
property bool isShowingMyItems: false;
|
||||
property bool isDebuggingFirstUseTutorial: false;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
Hifi.QmlCommerce {
|
||||
id: commerce;
|
||||
|
||||
onWalletStatusResult: {
|
||||
if (walletStatus === 0) {
|
||||
if (root.activeView !== "needsLogIn") {
|
||||
root.activeView = "needsLogIn";
|
||||
}
|
||||
} else if (walletStatus === 1) {
|
||||
if (root.activeView !== "notSetUp") {
|
||||
root.activeView = "notSetUp";
|
||||
notSetUpTimer.start();
|
||||
}
|
||||
} else if (walletStatus === 2) {
|
||||
if (root.activeView !== "passphraseModal") {
|
||||
root.activeView = "passphraseModal";
|
||||
}
|
||||
} else if (walletStatus === 3) {
|
||||
if ((Settings.getValue("isFirstUseOfPurchases", true) || root.isDebuggingFirstUseTutorial) && root.activeView !== "firstUseTutorial") {
|
||||
root.activeView = "firstUseTutorial";
|
||||
} else if (!Settings.getValue("isFirstUseOfPurchases", true) && root.activeView === "initialize") {
|
||||
root.activeView = "purchasesMain";
|
||||
commerce.inventory();
|
||||
}
|
||||
} else {
|
||||
console.log("ERROR in Purchases.qml: Unknown wallet status: " + walletStatus);
|
||||
}
|
||||
}
|
||||
|
||||
onLoginStatusResult: {
|
||||
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
||||
root.activeView = "needsLogIn";
|
||||
} else if (isLoggedIn) {
|
||||
root.activeView = "initialize";
|
||||
commerce.account();
|
||||
}
|
||||
}
|
||||
|
||||
onAccountResult: {
|
||||
if (result.status === "success") {
|
||||
commerce.getKeyFilePathIfExists();
|
||||
} else {
|
||||
// unsure how to handle a failure here. We definitely cannot proceed.
|
||||
}
|
||||
}
|
||||
|
||||
onKeyFilePathIfExistsResult: {
|
||||
if (path === "" && root.activeView !== "notSetUp") {
|
||||
root.activeView = "notSetUp";
|
||||
notSetUpTimer.start();
|
||||
} else if (path !== "" && root.activeView === "initialize") {
|
||||
commerce.getSecurityImage();
|
||||
}
|
||||
}
|
||||
|
||||
onSecurityImageResult: {
|
||||
securityImageResultReceived = true;
|
||||
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
|
||||
root.activeView = "notSetUp";
|
||||
notSetUpTimer.start();
|
||||
} else if (exists && root.activeView === "initialize") {
|
||||
commerce.getWalletAuthenticatedStatus();
|
||||
}
|
||||
}
|
||||
|
||||
onWalletAuthenticatedStatusResult: {
|
||||
if (!isAuthenticated && root.activeView !== "passphraseModal") {
|
||||
root.activeView = "passphraseModal";
|
||||
} else if (isAuthenticated) {
|
||||
sendToScript({method: 'purchases_getIsFirstUse'});
|
||||
commerce.getWalletStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,6 +114,19 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
HifiInspectionCertificate.InspectionCertificate {
|
||||
id: inspectionCertificate;
|
||||
z: 999;
|
||||
visible: false;
|
||||
anchors.fill: parent;
|
||||
|
||||
Connections {
|
||||
onSendToScript: {
|
||||
sendToScript(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiCommerceCommon.CommerceLightbox {
|
||||
id: lightboxPopup;
|
||||
visible: false;
|
||||
|
@ -165,6 +171,13 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
enabled: titleBarContainer.usernameDropdownVisible;
|
||||
anchors.fill: parent;
|
||||
onClicked: {
|
||||
titleBarContainer.usernameDropdownVisible = false;
|
||||
}
|
||||
}
|
||||
//
|
||||
// TITLE BAR END
|
||||
//
|
||||
|
@ -182,7 +195,7 @@ Rectangle {
|
|||
Component.onCompleted: {
|
||||
securityImageResultReceived = false;
|
||||
purchasesReceived = false;
|
||||
commerce.getLoginStatus();
|
||||
commerce.getWalletStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,7 +231,7 @@ Rectangle {
|
|||
onSendSignalToParent: {
|
||||
if (msg.method === "authSuccess") {
|
||||
root.activeView = "initialize";
|
||||
sendToScript({method: 'purchases_getIsFirstUse'});
|
||||
commerce.getWalletStatus();
|
||||
} else {
|
||||
sendToScript(msg);
|
||||
}
|
||||
|
@ -228,19 +241,16 @@ Rectangle {
|
|||
|
||||
FirstUseTutorial {
|
||||
id: firstUseTutorial;
|
||||
z: 999;
|
||||
visible: root.activeView === "firstUseTutorial";
|
||||
anchors.top: titleBarContainer.bottom;
|
||||
anchors.topMargin: -titleBarContainer.additionalDropdownHeight;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.fill: parent;
|
||||
|
||||
Connections {
|
||||
onSendSignalToParent: {
|
||||
switch (message.method) {
|
||||
case 'tutorial_skipClicked':
|
||||
case 'tutorial_finished':
|
||||
sendToScript({method: 'purchases_setIsFirstUse'});
|
||||
Settings.setValue("isFirstUseOfPurchases", false);
|
||||
root.activeView = "purchasesMain";
|
||||
commerce.inventory();
|
||||
break;
|
||||
|
@ -278,7 +288,7 @@ Rectangle {
|
|||
anchors.topMargin: 4;
|
||||
|
||||
RalewayRegular {
|
||||
id: myPurchasesText;
|
||||
id: myText;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 10;
|
||||
anchors.bottom: parent.bottom;
|
||||
|
@ -286,7 +296,7 @@ Rectangle {
|
|||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 4;
|
||||
width: paintedWidth;
|
||||
text: "My Purchases";
|
||||
text: isShowingMyItems ? "My Items" : "My Purchases";
|
||||
color: hifi.colors.baseGray;
|
||||
size: 28;
|
||||
}
|
||||
|
@ -296,7 +306,7 @@ Rectangle {
|
|||
colorScheme: hifi.colorSchemes.faintGray;
|
||||
hasClearButton: true;
|
||||
hasRoundedBorder: true;
|
||||
anchors.left: myPurchasesText.right;
|
||||
anchors.left: myText.right;
|
||||
anchors.leftMargin: 16;
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
|
@ -331,7 +341,7 @@ Rectangle {
|
|||
ListModel {
|
||||
id: previousPurchasesModel;
|
||||
}
|
||||
ListModel {
|
||||
HifiCommerceCommon.SortableListModel {
|
||||
id: filteredPurchasesModel;
|
||||
}
|
||||
|
||||
|
@ -400,7 +410,7 @@ Rectangle {
|
|||
|
||||
ListView {
|
||||
id: purchasesContentsList;
|
||||
visible: purchasesModel.count !== 0;
|
||||
visible: (root.isShowingMyItems && filteredPurchasesModel.count !== 0) || (!root.isShowingMyItems && filteredPurchasesModel.count !== 0);
|
||||
clip: true;
|
||||
model: filteredPurchasesModel;
|
||||
// Anchors
|
||||
|
@ -417,6 +427,8 @@ Rectangle {
|
|||
itemHref: root_file_url;
|
||||
purchaseStatus: status;
|
||||
purchaseStatusChanged: statusChanged;
|
||||
itemEdition: model.edition_number;
|
||||
displayedItemCount: model.displayedItemCount;
|
||||
anchors.topMargin: 12;
|
||||
anchors.bottomMargin: 12;
|
||||
|
||||
|
@ -425,6 +437,8 @@ Rectangle {
|
|||
if (msg.method === 'purchases_itemInfoClicked') {
|
||||
sendToScript({method: 'purchases_itemInfoClicked', itemId: itemId});
|
||||
} else if (msg.method === 'purchases_itemCertificateClicked') {
|
||||
inspectionCertificate.visible = true;
|
||||
inspectionCertificate.isLightbox = true;
|
||||
sendToScript(msg);
|
||||
} else if (msg.method === "showInvalidatedLightbox") {
|
||||
lightboxPopup.titleText = "Item Invalidated";
|
||||
|
@ -448,9 +462,55 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: noItemsAlertContainer;
|
||||
visible: !purchasesContentsList.visible && root.purchasesReceived && root.isShowingMyItems && filterBar.text === "";
|
||||
anchors.top: filterBarContainer.bottom;
|
||||
anchors.topMargin: 12;
|
||||
anchors.left: parent.left;
|
||||
anchors.bottom: parent.bottom;
|
||||
width: parent.width;
|
||||
|
||||
// Explanitory text
|
||||
RalewayRegular {
|
||||
id: noItemsYet;
|
||||
text: "<b>You haven't submitted anything to the Marketplace yet!</b><br><br>Submit an item to the Marketplace to add it to My Items.";
|
||||
// Text size
|
||||
size: 22;
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 150;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 24;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 24;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.baseGray;
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
}
|
||||
|
||||
// "Go To Marketplace" button
|
||||
HifiControlsUit.Button {
|
||||
color: hifi.buttons.blue;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: noItemsYet.bottom;
|
||||
anchors.topMargin: 20;
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
width: parent.width * 2 / 3;
|
||||
height: 50;
|
||||
text: "Visit Marketplace";
|
||||
onClicked: {
|
||||
sendToScript({method: 'purchases_goToMarketplaceClicked'});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: noPurchasesAlertContainer;
|
||||
visible: !purchasesContentsList.visible && root.purchasesReceived;
|
||||
visible: !purchasesContentsList.visible && root.purchasesReceived && !root.isShowingMyItems && filterBar.text === "";
|
||||
anchors.top: filterBarContainer.bottom;
|
||||
anchors.topMargin: 12;
|
||||
anchors.left: parent.left;
|
||||
|
@ -478,7 +538,7 @@ Rectangle {
|
|||
horizontalAlignment: Text.AlignHCenter;
|
||||
}
|
||||
|
||||
// "Set Up" button
|
||||
// "Go To Marketplace" button
|
||||
HifiControlsUit.Button {
|
||||
color: hifi.buttons.blue;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
|
@ -530,17 +590,43 @@ Rectangle {
|
|||
// FUNCTION DEFINITIONS START
|
||||
//
|
||||
|
||||
function populateDisplayedItemCounts() {
|
||||
var itemCountDictionary = {};
|
||||
var currentItemId;
|
||||
for (var i = 0; i < filteredPurchasesModel.count; i++) {
|
||||
currentItemId = filteredPurchasesModel.get(i).id;
|
||||
if (itemCountDictionary[currentItemId] === undefined) {
|
||||
itemCountDictionary[currentItemId] = 1;
|
||||
} else {
|
||||
itemCountDictionary[currentItemId]++;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < filteredPurchasesModel.count; i++) {
|
||||
filteredPurchasesModel.setProperty(i, "displayedItemCount", itemCountDictionary[filteredPurchasesModel.get(i).id]);
|
||||
}
|
||||
}
|
||||
|
||||
function sortByDate() {
|
||||
filteredPurchasesModel.sortColumnName = "purchase_date";
|
||||
filteredPurchasesModel.isSortingDescending = false;
|
||||
filteredPurchasesModel.quickSort();
|
||||
}
|
||||
|
||||
function buildFilteredPurchasesModel() {
|
||||
filteredPurchasesModel.clear();
|
||||
for (var i = 0; i < purchasesModel.count; i++) {
|
||||
if (purchasesModel.get(i).title.toLowerCase().indexOf(filterBar.text.toLowerCase()) !== -1) {
|
||||
if (purchasesModel.get(i).status !== "confirmed") {
|
||||
if (purchasesModel.get(i).status !== "confirmed" && !root.isShowingMyItems) {
|
||||
filteredPurchasesModel.insert(0, purchasesModel.get(i));
|
||||
} else {
|
||||
} else if ((root.isShowingMyItems && purchasesModel.get(i).edition_number === -1) || !root.isShowingMyItems) {
|
||||
filteredPurchasesModel.append(purchasesModel.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
populateDisplayedItemCounts();
|
||||
sortByDate();
|
||||
}
|
||||
|
||||
function checkIfAnyItemStatusChanged() {
|
||||
|
@ -581,16 +667,14 @@ Rectangle {
|
|||
case 'updatePurchases':
|
||||
referrerURL = message.referrerURL;
|
||||
titleBarContainer.referrerURL = message.referrerURL;
|
||||
root.canRezCertifiedItems = message.canRezCertifiedItems;
|
||||
filterBar.text = message.filterText ? message.filterText : "";
|
||||
break;
|
||||
case 'purchases_getIsFirstUseResult':
|
||||
if (message.isFirstUseOfPurchases && root.activeView !== "firstUseTutorial") {
|
||||
root.activeView = "firstUseTutorial";
|
||||
} else if (!message.isFirstUseOfPurchases && root.activeView === "initialize") {
|
||||
root.activeView = "purchasesMain";
|
||||
commerce.inventory();
|
||||
}
|
||||
case 'inspectionCertificate_setMarketplaceId':
|
||||
case 'inspectionCertificate_setItemInfo':
|
||||
inspectionCertificate.fromScript(message);
|
||||
break;
|
||||
case 'purchases_showMyItems':
|
||||
root.isShowingMyItems = true;
|
||||
break;
|
||||
default:
|
||||
console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message));
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
Binary file not shown.
After Width: | Height: | Size: 81 KiB |
|
@ -90,7 +90,7 @@ Item {
|
|||
} else {
|
||||
// Error submitting new passphrase
|
||||
resetSubmitButton();
|
||||
passphraseSelection.setErrorText("Backend error");
|
||||
passphraseSelection.setErrorText("Current passphrase incorrect - try again");
|
||||
}
|
||||
} else {
|
||||
sendSignalToWallet(msg);
|
||||
|
@ -137,9 +137,10 @@ Item {
|
|||
width: 150;
|
||||
text: "Submit";
|
||||
onClicked: {
|
||||
if (passphraseSelection.validateAndSubmitPassphrase()) {
|
||||
passphraseSubmitButton.text = "Submitting...";
|
||||
passphraseSubmitButton.enabled = false;
|
||||
passphraseSubmitButton.text = "Submitting...";
|
||||
passphraseSubmitButton.enabled = false;
|
||||
if (!passphraseSelection.validateAndSubmitPassphrase()) {
|
||||
resetSubmitButton();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,6 +129,7 @@ Item {
|
|||
width: height;
|
||||
fillMode: Image.PreserveAspectFit;
|
||||
mipmap: true;
|
||||
cache: false;
|
||||
|
||||
MouseArea {
|
||||
enabled: titleBarSecurityImage.visible;
|
||||
|
|
|
@ -26,6 +26,7 @@ Item {
|
|||
id: root;
|
||||
property bool isChangingPassphrase: false;
|
||||
property bool isShowingTip: false;
|
||||
property bool shouldImmediatelyFocus: true;
|
||||
|
||||
// This object is always used in a popup.
|
||||
// This MouseArea is used to prevent a user from being
|
||||
|
@ -42,8 +43,8 @@ Item {
|
|||
passphrasePageSecurityImage.source = "image://security/securityImage";
|
||||
}
|
||||
|
||||
onWalletAuthenticatedStatusResult: {
|
||||
sendMessageToLightbox({method: 'statusResult', status: isAuthenticated});
|
||||
onChangePassphraseStatusResult: {
|
||||
sendMessageToLightbox({method: 'statusResult', status: changeSuccess});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,10 +54,8 @@ Item {
|
|||
// TODO: Fix this unlikely bug
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
if (root.isChangingPassphrase) {
|
||||
currentPassphraseField.focus = true;
|
||||
} else {
|
||||
passphraseField.focus = true;
|
||||
if (root.shouldImmediatelyFocus) {
|
||||
focusFirstTextField();
|
||||
}
|
||||
sendMessageToLightbox({method: 'disableHmdPreview'});
|
||||
} else {
|
||||
|
@ -311,7 +310,7 @@ Item {
|
|||
passphraseFieldAgain.error = false;
|
||||
currentPassphraseField.error = false;
|
||||
setErrorText("");
|
||||
commerce.setPassphrase(passphraseField.text);
|
||||
commerce.changePassphrase(currentPassphraseField.text, passphraseField.text);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -327,5 +326,13 @@ Item {
|
|||
setErrorText("");
|
||||
}
|
||||
|
||||
function focusFirstTextField() {
|
||||
if (root.isChangingPassphrase) {
|
||||
currentPassphraseField.focus = true;
|
||||
} else {
|
||||
passphraseField.focus = true;
|
||||
}
|
||||
}
|
||||
|
||||
signal sendMessageToLightbox(var msg);
|
||||
}
|
||||
|
|
|
@ -280,6 +280,34 @@ Item {
|
|||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: removeHmdContainer;
|
||||
z: 998;
|
||||
visible: false;
|
||||
color: hifi.colors.blueHighlight;
|
||||
anchors.fill: backupInstructionsButton;
|
||||
radius: 5;
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
propagateComposedEvents: false;
|
||||
}
|
||||
|
||||
RalewayBold {
|
||||
anchors.fill: parent;
|
||||
text: "INSTRUCTIONS OPEN ON DESKTOP";
|
||||
size: 15;
|
||||
color: hifi.colors.white;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: removeHmdContainerTimer;
|
||||
interval: 5000;
|
||||
onTriggered: removeHmdContainer.visible = false
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.Button {
|
||||
id: backupInstructionsButton;
|
||||
text: "View Backup Instructions";
|
||||
|
@ -293,6 +321,9 @@ Item {
|
|||
|
||||
onClicked: {
|
||||
Qt.openUrlExternally("https://www.highfidelity.com/");
|
||||
Qt.openUrlExternally("file:///" + root.keyFilePath.substring(0, root.keyFilePath.lastIndexOf('/')));
|
||||
removeHmdContainer.visible = true;
|
||||
removeHmdContainerTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ Item {
|
|||
anchors.verticalCenter: parent.verticalCenter;
|
||||
fillMode: Image.PreserveAspectFit;
|
||||
mipmap: true;
|
||||
cache: false;
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
|
|
|
@ -38,48 +38,41 @@ Rectangle {
|
|||
Hifi.QmlCommerce {
|
||||
id: commerce;
|
||||
|
||||
onWalletStatusResult: {
|
||||
if (walletStatus === 0) {
|
||||
if (root.activeView !== "needsLogIn") {
|
||||
root.activeView = "needsLogIn";
|
||||
}
|
||||
} else if (walletStatus === 1) {
|
||||
if (root.activeView !== "walletSetup") {
|
||||
root.activeView = "walletSetup";
|
||||
}
|
||||
} else if (walletStatus === 2) {
|
||||
if (root.activeView !== "passphraseModal") {
|
||||
root.activeView = "passphraseModal";
|
||||
}
|
||||
} else if (walletStatus === 3) {
|
||||
root.activeView = "walletHome";
|
||||
commerce.getSecurityImage();
|
||||
} else {
|
||||
console.log("ERROR in Wallet.qml: Unknown wallet status: " + walletStatus);
|
||||
}
|
||||
}
|
||||
|
||||
onLoginStatusResult: {
|
||||
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
||||
root.activeView = "needsLogIn";
|
||||
} else if (isLoggedIn) {
|
||||
root.activeView = "initialize";
|
||||
commerce.account();
|
||||
}
|
||||
}
|
||||
|
||||
onAccountResult: {
|
||||
if (result.status === "success") {
|
||||
commerce.getKeyFilePathIfExists();
|
||||
} else {
|
||||
// unsure how to handle a failure here. We definitely cannot proceed.
|
||||
}
|
||||
}
|
||||
|
||||
onKeyFilePathIfExistsResult: {
|
||||
if (path === "" && root.activeView !== "walletSetup") {
|
||||
root.activeView = "walletSetup";
|
||||
} else if (path !== "" && root.activeView === "initialize") {
|
||||
commerce.getSecurityImage();
|
||||
commerce.getWalletStatus();
|
||||
}
|
||||
}
|
||||
|
||||
onSecurityImageResult: {
|
||||
if (!exists && root.activeView !== "walletSetup") { // "If security image is not set up"
|
||||
root.activeView = "walletSetup";
|
||||
} else if (exists && root.activeView === "initialize") {
|
||||
commerce.getWalletAuthenticatedStatus();
|
||||
if (exists) {
|
||||
titleBarSecurityImage.source = "";
|
||||
titleBarSecurityImage.source = "image://security/securityImage";
|
||||
}
|
||||
}
|
||||
|
||||
onWalletAuthenticatedStatusResult: {
|
||||
if (!isAuthenticated && passphraseModal && root.activeView !== "passphraseModal") {
|
||||
root.activeView = "passphraseModal";
|
||||
} else if (isAuthenticated) {
|
||||
root.activeView = "walletHome";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SecurityImageModel {
|
||||
|
@ -149,6 +142,7 @@ Rectangle {
|
|||
anchors.bottomMargin: 6;
|
||||
width: height;
|
||||
mipmap: true;
|
||||
cache: false;
|
||||
|
||||
MouseArea {
|
||||
enabled: titleBarSecurityImage.visible;
|
||||
|
@ -179,7 +173,7 @@ Rectangle {
|
|||
if (msg.method === 'walletSetup_finished') {
|
||||
if (msg.referrer === '') {
|
||||
root.activeView = "initialize";
|
||||
commerce.getLoginStatus();
|
||||
commerce.getWalletStatus();
|
||||
} else if (msg.referrer === 'purchases') {
|
||||
sendToScript({method: 'goToPurchases'});
|
||||
}
|
||||
|
@ -254,7 +248,7 @@ Rectangle {
|
|||
color: hifi.colors.baseGray;
|
||||
|
||||
Component.onCompleted: {
|
||||
commerce.getLoginStatus();
|
||||
commerce.getWalletStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ Item {
|
|||
|
||||
id: root;
|
||||
property bool historyReceived: false;
|
||||
property int pendingCount: 0;
|
||||
|
||||
Hifi.QmlCommerce {
|
||||
id: commerce;
|
||||
|
@ -39,6 +40,8 @@ Item {
|
|||
if (result.status === 'success') {
|
||||
transactionHistoryModel.clear();
|
||||
transactionHistoryModel.append(result.data.history);
|
||||
|
||||
calculatePendingAndInvalidated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -200,55 +203,74 @@ Item {
|
|||
model: transactionHistoryModel;
|
||||
delegate: Item {
|
||||
width: parent.width;
|
||||
height: transactionText.height + 30;
|
||||
height: (model.transaction_type === "pendingCount" && root.pendingCount !== 0) ? 40 : ((model.status === "confirmed" || model.status === "invalidated") ? transactionText.height + 30 : 0);
|
||||
|
||||
HifiControlsUit.Separator {
|
||||
visible: index === 0;
|
||||
colorScheme: 1;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.top: parent.top;
|
||||
}
|
||||
|
||||
AnonymousProRegular {
|
||||
id: dateText;
|
||||
text: getFormattedDate(model.created_at * 1000);
|
||||
// Style
|
||||
size: 18;
|
||||
Item {
|
||||
visible: model.transaction_type === "pendingCount" && root.pendingCount !== 0;
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 15;
|
||||
width: 118;
|
||||
height: paintedHeight;
|
||||
color: hifi.colors.blueAccent;
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignRight;
|
||||
}
|
||||
width: parent.width;
|
||||
height: visible ? parent.height : 0;
|
||||
|
||||
AnonymousProRegular {
|
||||
id: transactionText;
|
||||
text: model.text;
|
||||
size: 18;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 15;
|
||||
anchors.left: dateText.right;
|
||||
anchors.leftMargin: 20;
|
||||
anchors.right: parent.right;
|
||||
height: paintedHeight;
|
||||
color: hifi.colors.baseGrayHighlight;
|
||||
wrapMode: Text.WordWrap;
|
||||
|
||||
onLinkActivated: {
|
||||
sendSignalToWallet({method: 'transactionHistory_linkClicked', marketplaceLink: link});
|
||||
AnonymousProRegular {
|
||||
id: pendingCountText;
|
||||
anchors.fill: parent;
|
||||
text: root.pendingCount + ' Transaction' + (root.pendingCount > 1 ? 's' : '') + ' Pending';
|
||||
size: 18;
|
||||
color: hifi.colors.blueAccent;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.Separator {
|
||||
colorScheme: 1;
|
||||
Item {
|
||||
visible: model.transaction_type !== "pendingCount" && (model.status === "confirmed" || model.status === "invalidated");
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.bottom: parent.bottom;
|
||||
width: parent.width;
|
||||
height: visible ? parent.height : 0;
|
||||
|
||||
AnonymousProRegular {
|
||||
id: dateText;
|
||||
text: model.created_at ? getFormattedDate(model.created_at * 1000) : "";
|
||||
// Style
|
||||
size: 18;
|
||||
anchors.left: parent.left;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 15;
|
||||
width: 118;
|
||||
height: paintedHeight;
|
||||
color: hifi.colors.blueAccent;
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignRight;
|
||||
}
|
||||
|
||||
AnonymousProRegular {
|
||||
id: transactionText;
|
||||
text: model.text ? (model.status === "invalidated" ? ("INVALIDATED: " + model.text) : model.text) : "";
|
||||
size: 18;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 15;
|
||||
anchors.left: dateText.right;
|
||||
anchors.leftMargin: 20;
|
||||
anchors.right: parent.right;
|
||||
height: paintedHeight;
|
||||
color: model.status === "invalidated" ? hifi.colors.redAccent : hifi.colors.baseGrayHighlight;
|
||||
wrapMode: Text.WordWrap;
|
||||
font.strikeout: model.status === "invalidated";
|
||||
|
||||
onLinkActivated: {
|
||||
sendSignalToWallet({method: 'transactionHistory_linkClicked', marketplaceLink: link});
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.Separator {
|
||||
colorScheme: 1;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.bottom: parent.bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
onAtYEndChanged: {
|
||||
|
@ -299,6 +321,19 @@ Item {
|
|||
return year + '-' + month + '-' + day + '<br>' + drawnHour + ':' + min + amOrPm;
|
||||
}
|
||||
|
||||
|
||||
function calculatePendingAndInvalidated(startingPendingCount) {
|
||||
var pendingCount = startingPendingCount ? startingPendingCount : 0;
|
||||
for (var i = 0; i < transactionHistoryModel.count; i++) {
|
||||
if (transactionHistoryModel.get(i).status === "pending") {
|
||||
pendingCount++;
|
||||
}
|
||||
}
|
||||
|
||||
root.pendingCount = pendingCount;
|
||||
transactionHistoryModel.insert(0, {"transaction_type": "pendingCount"});
|
||||
}
|
||||
|
||||
//
|
||||
// Function Name: fromScript()
|
||||
//
|
||||
|
|
|
@ -43,7 +43,7 @@ Item {
|
|||
if (!exists && root.lastPage === "step_2") {
|
||||
// ERROR! Invalid security image.
|
||||
root.activeView = "step_2";
|
||||
} else {
|
||||
} else if (exists) {
|
||||
titleBarSecurityImage.source = "";
|
||||
titleBarSecurityImage.source = "image://security/securityImage";
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ Item {
|
|||
Image {
|
||||
id: titleBarSecurityImage;
|
||||
source: "";
|
||||
visible: !securityImageTip.visible && titleBarSecurityImage.source !== "";
|
||||
visible: !securityImageTip.visible && titleBarSecurityImage.source !== "" && root.activeView !== "step_1" && root.activeView !== "step_2";
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 6;
|
||||
anchors.top: parent.top;
|
||||
|
@ -125,6 +125,7 @@ Item {
|
|||
anchors.bottomMargin: 6;
|
||||
width: height;
|
||||
mipmap: true;
|
||||
cache: false;
|
||||
|
||||
MouseArea {
|
||||
enabled: titleBarSecurityImage.visible;
|
||||
|
@ -422,6 +423,7 @@ Item {
|
|||
onClicked: {
|
||||
root.hasShownSecurityImageTip = true;
|
||||
securityImageTip.visible = false;
|
||||
passphraseSelection.focusFirstTextField();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -466,6 +468,7 @@ Item {
|
|||
|
||||
PassphraseSelection {
|
||||
id: passphraseSelection;
|
||||
shouldImmediatelyFocus: root.hasShownSecurityImageTip;
|
||||
isShowingTip: securityImageTip.visible;
|
||||
anchors.top: passphraseTitleHelper.bottom;
|
||||
anchors.topMargin: 30;
|
||||
|
@ -680,6 +683,7 @@ Item {
|
|||
instructions02Container.visible = true;
|
||||
keysReadyPageFinishButton.visible = true;
|
||||
Qt.openUrlExternally("https://www.highfidelity.com/");
|
||||
Qt.openUrlExternally("file:///" + root.keyFilePath.substring(0, root.keyFilePath.lastIndexOf('/')));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,6 +167,7 @@
|
|||
#include "scripting/ControllerScriptingInterface.h"
|
||||
#include "scripting/RatesScriptingInterface.h"
|
||||
#include "scripting/SelectionScriptingInterface.h"
|
||||
#include "scripting/WalletScriptingInterface.h"
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
#include "SpeechRecognizer.h"
|
||||
#endif
|
||||
|
@ -687,6 +688,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
DependencyManager::set<ContextOverlayInterface>();
|
||||
DependencyManager::set<Ledger>();
|
||||
DependencyManager::set<Wallet>();
|
||||
DependencyManager::set<WalletScriptingInterface>();
|
||||
|
||||
DependencyManager::set<FadeEffect>();
|
||||
|
||||
|
@ -2331,6 +2333,7 @@ void Application::initializeUi() {
|
|||
surfaceContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
|
||||
surfaceContext->setContextProperty("Selection", DependencyManager::get<SelectionScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
|
||||
surfaceContext->setContextProperty("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
|
||||
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
||||
surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
|
||||
|
@ -6058,6 +6061,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
|||
scriptEngine->registerGlobalObject("AvatarInputs", AvatarInputs::getInstance());
|
||||
scriptEngine->registerGlobalObject("Selection", DependencyManager::get<SelectionScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
|
||||
scriptEngine->registerGlobalObject("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
|
||||
qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
|
||||
|
||||
|
|
|
@ -164,11 +164,7 @@ void Ledger::historySuccess(QNetworkReply& reply) {
|
|||
// turns out on my machine, toLocalTime convert to some weird timezone, yet the
|
||||
// systemTimeZone is correct. To avoid a strange bug with other's systems too, lets
|
||||
// be explicit
|
||||
#ifdef Q_OS_MAC
|
||||
QDateTime createdAt = QDateTime::fromTime_t(valueObject["created_at"].toInt(), Qt::UTC);
|
||||
#else
|
||||
QDateTime createdAt = QDateTime::fromSecsSinceEpoch(valueObject["created_at"].toInt(), Qt::UTC);
|
||||
#endif
|
||||
QDateTime localCreatedAt = createdAt.toTimeZone(QTimeZone::systemTimeZone());
|
||||
valueObject["text"] = QString("%1 sent %2 %3 with message \"%4\"").
|
||||
arg(from, to, coloredQuantityAndAssetTitle, valueObject["message"].toString());
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "Ledger.h"
|
||||
#include "Wallet.h"
|
||||
#include <AccountManager.h>
|
||||
#include "scripting/WalletScriptingInterface.h"
|
||||
|
||||
HIFI_QML_DEF(QmlCommerce)
|
||||
|
||||
|
@ -28,6 +29,37 @@ QmlCommerce::QmlCommerce(QQuickItem* parent) : OffscreenQmlDialog(parent) {
|
|||
connect(ledger.data(), &Ledger::historyResult, this, &QmlCommerce::historyResult);
|
||||
connect(wallet.data(), &Wallet::keyFilePathIfExistsResult, this, &QmlCommerce::keyFilePathIfExistsResult);
|
||||
connect(ledger.data(), &Ledger::accountResult, this, &QmlCommerce::accountResult);
|
||||
connect(ledger.data(), &Ledger::accountResult, this, [&]() {
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
auto walletScriptingInterface = DependencyManager::get<WalletScriptingInterface>();
|
||||
uint status;
|
||||
|
||||
if (wallet->getKeyFilePath() == "" || !wallet->getSecurityImage()) {
|
||||
status = (uint)WalletStatus::WALLET_STATUS_NOT_SET_UP;
|
||||
} else if (!wallet->walletIsAuthenticatedWithPassphrase()) {
|
||||
status = (uint)WalletStatus::WALLET_STATUS_NOT_AUTHENTICATED;
|
||||
} else {
|
||||
status = (uint)WalletStatus::WALLET_STATUS_READY;
|
||||
}
|
||||
|
||||
walletScriptingInterface->setWalletStatus(status);
|
||||
emit walletStatusResult(status);
|
||||
});
|
||||
}
|
||||
|
||||
void QmlCommerce::getWalletStatus() {
|
||||
auto walletScriptingInterface = DependencyManager::get<WalletScriptingInterface>();
|
||||
uint status;
|
||||
|
||||
if (DependencyManager::get<AccountManager>()->isLoggedIn()) {
|
||||
// This will set account info for the wallet, allowing us to decrypt and display the security image.
|
||||
account();
|
||||
} else {
|
||||
status = (uint)WalletStatus::WALLET_STATUS_NOT_LOGGED_IN;
|
||||
emit walletStatusResult(status);
|
||||
walletScriptingInterface->setWalletStatus(status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void QmlCommerce::getLoginStatus() {
|
||||
|
@ -36,7 +68,7 @@ void QmlCommerce::getLoginStatus() {
|
|||
|
||||
void QmlCommerce::getKeyFilePathIfExists() {
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
wallet->sendKeyFilePathIfExists();
|
||||
emit keyFilePathIfExistsResult(wallet->getKeyFilePath());
|
||||
}
|
||||
|
||||
void QmlCommerce::getWalletAuthenticatedStatus() {
|
||||
|
@ -85,13 +117,18 @@ void QmlCommerce::history() {
|
|||
ledger->history(wallet->listPublicKeys());
|
||||
}
|
||||
|
||||
void QmlCommerce::changePassphrase(const QString& oldPassphrase, const QString& newPassphrase) {
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
if ((wallet->getPassphrase()->isEmpty() || wallet->getPassphrase() == oldPassphrase) && !newPassphrase.isEmpty()) {
|
||||
emit changePassphraseStatusResult(wallet->changePassphrase(newPassphrase));
|
||||
} else {
|
||||
emit changePassphraseStatusResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
void QmlCommerce::setPassphrase(const QString& passphrase) {
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
if(wallet->getPassphrase() && !wallet->getPassphrase()->isEmpty() && !passphrase.isEmpty()) {
|
||||
wallet->changePassphrase(passphrase);
|
||||
} else {
|
||||
wallet->setPassphrase(passphrase);
|
||||
}
|
||||
wallet->setPassphrase(passphrase);
|
||||
getWalletAuthenticatedStatus();
|
||||
}
|
||||
|
||||
|
|
|
@ -27,11 +27,21 @@ class QmlCommerce : public OffscreenQmlDialog {
|
|||
public:
|
||||
QmlCommerce(QQuickItem* parent = nullptr);
|
||||
|
||||
enum WalletStatus {
|
||||
WALLET_STATUS_NOT_LOGGED_IN = 0,
|
||||
WALLET_STATUS_NOT_SET_UP,
|
||||
WALLET_STATUS_NOT_AUTHENTICATED,
|
||||
WALLET_STATUS_READY
|
||||
};
|
||||
|
||||
signals:
|
||||
void walletStatusResult(uint walletStatus);
|
||||
|
||||
void loginStatusResult(bool isLoggedIn);
|
||||
void keyFilePathIfExistsResult(const QString& path);
|
||||
void securityImageResult(bool exists);
|
||||
void walletAuthenticatedStatusResult(bool isAuthenticated);
|
||||
void changePassphraseStatusResult(bool changeSuccess);
|
||||
|
||||
void buyResult(QJsonObject result);
|
||||
// Balance and Inventory are NOT properties, because QML can't change them (without risk of failure), and
|
||||
|
@ -42,6 +52,8 @@ signals:
|
|||
void accountResult(QJsonObject result);
|
||||
|
||||
protected:
|
||||
Q_INVOKABLE void getWalletStatus();
|
||||
|
||||
Q_INVOKABLE void getLoginStatus();
|
||||
Q_INVOKABLE void getKeyFilePathIfExists();
|
||||
Q_INVOKABLE void getSecurityImage();
|
||||
|
@ -49,6 +61,7 @@ protected:
|
|||
|
||||
Q_INVOKABLE void chooseSecurityImage(const QString& imageFile);
|
||||
Q_INVOKABLE void setPassphrase(const QString& passphrase);
|
||||
Q_INVOKABLE void changePassphrase(const QString& oldPassphrase, const QString& newPassphrase);
|
||||
|
||||
Q_INVOKABLE void buy(const QString& assetId, int cost, const bool controlledFailure = false);
|
||||
Q_INVOKABLE void balance();
|
||||
|
|
|
@ -284,7 +284,7 @@ Wallet::Wallet() {
|
|||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
auto& packetReceiver = nodeList->getPacketReceiver();
|
||||
|
||||
packetReceiver.registerListener(PacketType::ChallengeOwnership, this, "verifyOwnerChallenge");
|
||||
packetReceiver.registerListener(PacketType::ChallengeOwnership, this, "handleChallengeOwnershipPacket");
|
||||
}
|
||||
|
||||
Wallet::~Wallet() {
|
||||
|
@ -468,7 +468,7 @@ bool Wallet::generateKeyPair() {
|
|||
|
||||
// TODO: redo this soon -- need error checking and so on
|
||||
writeSecurityImage(_securityImage, keyFilePath());
|
||||
sendKeyFilePathIfExists();
|
||||
emit keyFilePathIfExistsResult(getKeyFilePath());
|
||||
QString oldKey = _publicKeys.count() == 0 ? "" : _publicKeys.last();
|
||||
QString key = keyPair.first->toBase64();
|
||||
_publicKeys.push_back(key);
|
||||
|
@ -559,14 +559,14 @@ void Wallet::chooseSecurityImage(const QString& filename) {
|
|||
emit securityImageResult(success);
|
||||
}
|
||||
|
||||
void Wallet::getSecurityImage() {
|
||||
bool Wallet::getSecurityImage() {
|
||||
unsigned char* data;
|
||||
int dataLen;
|
||||
|
||||
// if already decrypted, don't do it again
|
||||
if (_securityImage) {
|
||||
emit securityImageResult(true);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
|
@ -585,14 +585,15 @@ void Wallet::getSecurityImage() {
|
|||
success = true;
|
||||
}
|
||||
emit securityImageResult(success);
|
||||
return success;
|
||||
}
|
||||
void Wallet::sendKeyFilePathIfExists() {
|
||||
QString Wallet::getKeyFilePath() {
|
||||
QString filePath(keyFilePath());
|
||||
QFileInfo fileInfo(filePath);
|
||||
if (fileInfo.exists()) {
|
||||
emit keyFilePathIfExistsResult(filePath);
|
||||
return filePath;
|
||||
} else {
|
||||
emit keyFilePathIfExistsResult("");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@ public:
|
|||
QStringList listPublicKeys();
|
||||
QString signWithKey(const QByteArray& text, const QString& key);
|
||||
void chooseSecurityImage(const QString& imageFile);
|
||||
void getSecurityImage();
|
||||
void sendKeyFilePathIfExists();
|
||||
bool getSecurityImage();
|
||||
QString getKeyFilePath();
|
||||
|
||||
void setSalt(const QByteArray& salt) { _salt = salt; }
|
||||
QByteArray getSalt() { return _salt; }
|
||||
|
|
47
interface/src/scripting/WalletScriptingInterface.cpp
Normal file
47
interface/src/scripting/WalletScriptingInterface.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// WalletScriptingInterface.cpp
|
||||
// interface/src/scripting
|
||||
//
|
||||
// Created by Zach Fox on 2017-09-29.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "WalletScriptingInterface.h"
|
||||
|
||||
CheckoutProxy::CheckoutProxy(QObject* qmlObject, QObject* parent) : QmlWrapper(qmlObject, parent) {
|
||||
Q_ASSERT(QThread::currentThread() == qApp->thread());
|
||||
}
|
||||
|
||||
WalletScriptingInterface::WalletScriptingInterface() {
|
||||
}
|
||||
|
||||
static const QString CHECKOUT_QML_PATH = qApp->applicationDirPath() + "../../../qml/hifi/commerce/checkout/Checkout.qml";
|
||||
void WalletScriptingInterface::buy(const QString& name, const QString& id, const int& price, const QString& href) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "buy", Q_ARG(const QString&, name), Q_ARG(const QString&, id), Q_ARG(const int&, price), Q_ARG(const QString&, href));
|
||||
return;
|
||||
}
|
||||
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
||||
|
||||
tablet->loadQMLSource(CHECKOUT_QML_PATH);
|
||||
DependencyManager::get<HMDScriptingInterface>()->openTablet();
|
||||
|
||||
QQuickItem* root = nullptr;
|
||||
if (tablet->getToolbarMode() || (!tablet->getTabletRoot() && !qApp->isHMDMode())) {
|
||||
root = DependencyManager::get<OffscreenUi>()->getRootItem();
|
||||
} else {
|
||||
root = tablet->getTabletRoot();
|
||||
}
|
||||
CheckoutProxy* checkout = new CheckoutProxy(root->findChild<QObject*>("checkout"));
|
||||
|
||||
// Example: Wallet.buy("Test Flaregun", "0d90d21c-ce7a-4990-ad18-e9d2cf991027", 17, "http://mpassets.highfidelity.com/0d90d21c-ce7a-4990-ad18-e9d2cf991027-v1/flaregun.json");
|
||||
checkout->writeProperty("itemName", name);
|
||||
checkout->writeProperty("itemId", id);
|
||||
checkout->writeProperty("itemPrice", price);
|
||||
checkout->writeProperty("itemHref", href);
|
||||
}
|
51
interface/src/scripting/WalletScriptingInterface.h
Normal file
51
interface/src/scripting/WalletScriptingInterface.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
|
||||
// WalletScriptingInterface.h
|
||||
// interface/src/scripting
|
||||
//
|
||||
// Created by Zach Fox on 2017-09-29.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_WalletScriptingInterface_h
|
||||
#define hifi_WalletScriptingInterface_h
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <DependencyManager.h>
|
||||
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include <ui/TabletScriptingInterface.h>
|
||||
#include <ui/QmlWrapper.h>
|
||||
#include <OffscreenUi.h>
|
||||
#include "Application.h"
|
||||
|
||||
class CheckoutProxy : public QmlWrapper {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CheckoutProxy(QObject* qmlObject, QObject* parent = nullptr);
|
||||
};
|
||||
|
||||
|
||||
class WalletScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(uint walletStatus READ getWalletStatus WRITE setWalletStatus NOTIFY walletStatusChanged)
|
||||
|
||||
public:
|
||||
WalletScriptingInterface();
|
||||
|
||||
Q_INVOKABLE uint getWalletStatus() { return _walletStatus; }
|
||||
void setWalletStatus(const uint& status) { _walletStatus = status; }
|
||||
|
||||
Q_INVOKABLE void buy(const QString& name, const QString& id, const int& price, const QString& href);
|
||||
|
||||
signals:
|
||||
void walletStatusChanged();
|
||||
|
||||
private:
|
||||
uint _walletStatus;
|
||||
};
|
||||
|
||||
#endif // hifi_WalletScriptingInterface_h
|
|
@ -201,7 +201,8 @@ bool ContextOverlayInterface::destroyContextOverlay(const EntityItemID& entityIt
|
|||
void ContextOverlayInterface::contextOverlays_mousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event) {
|
||||
if (overlayID == _contextOverlayID && event.getButton() == PointerEvent::PrimaryButton) {
|
||||
qCDebug(context_overlay) << "Clicked Context Overlay. Entity ID:" << _currentEntityWithContextOverlay << "Overlay ID:" << overlayID;
|
||||
if (_commerceSettingSwitch.get()) {
|
||||
Setting::Handle<bool> _settingSwitch{ "commerce", false };
|
||||
if (_settingSwitch.get()) {
|
||||
openInspectionCertificate();
|
||||
} else {
|
||||
openMarketplace();
|
||||
|
|
|
@ -79,8 +79,6 @@ private:
|
|||
|
||||
bool _isInMarketplaceInspectionMode { false };
|
||||
|
||||
Setting::Handle<bool> _commerceSettingSwitch{ "commerce", false };
|
||||
|
||||
void openInspectionCertificate();
|
||||
void openMarketplace();
|
||||
void enableEntityHighlight(const EntityItemID& entityItemID);
|
||||
|
|
|
@ -61,7 +61,7 @@ void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info)
|
|||
|
||||
// During the period in which we have HFC commerce in the system, but not applied everywhere:
|
||||
const QString tokenStringCommerce{ "Chrome/48.0 (HighFidelityInterface WithHFC)" };
|
||||
static Setting::Handle<bool> _settingSwitch{ "commerce", false };
|
||||
Setting::Handle<bool> _settingSwitch{ "commerce", false };
|
||||
bool isMoney = _settingSwitch.get();
|
||||
|
||||
const QString tokenString = !isAuthable ? tokenStringMobile : (isMoney ? tokenStringCommerce : tokenStringMetaverse);
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
onButtonClicked();
|
||||
break;
|
||||
case 'walletReset':
|
||||
Settings.setValue("isFirstUseOfPurchases", true);
|
||||
onButtonClicked();
|
||||
onButtonClicked();
|
||||
break;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
var confirmAllPurchases = false; // Set this to "true" to cause Checkout.qml to popup for all items, even if free
|
||||
var userIsLoggedIn = false;
|
||||
var walletNeedsSetup = false;
|
||||
|
||||
function injectCommonCode(isDirectoryPage) {
|
||||
|
||||
|
@ -91,6 +92,48 @@
|
|||
});
|
||||
}
|
||||
|
||||
emitWalletSetupEvent = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "WALLET_SETUP"
|
||||
}));
|
||||
}
|
||||
|
||||
function maybeAddSetupWalletButton() {
|
||||
if (userIsLoggedIn && walletNeedsSetup) {
|
||||
var resultsElement = document.getElementById('results');
|
||||
var setupWalletElement = document.createElement('div');
|
||||
setupWalletElement.classList.add("row");
|
||||
setupWalletElement.id = "setupWalletDiv";
|
||||
setupWalletElement.style = "height:60px;margin:20px 10px 10px 10px;padding:12px 5px;" +
|
||||
"background-color:#D6F4D8;border-color:#aee9b2;border-width:2px;border-style:solid;border-radius:5px;";
|
||||
|
||||
var span = document.createElement('span');
|
||||
span.style = "margin:10px 5px;color:#1b6420;font-size:15px;";
|
||||
span.innerHTML = "<a href='#' onclick='emitWalletSetupEvent(); return false;'>Setup your Wallet</a> to get money and shop in Marketplace.";
|
||||
|
||||
var xButton = document.createElement('a');
|
||||
xButton.id = "xButton";
|
||||
xButton.setAttribute('href', "#");
|
||||
xButton.style = "width:50px;height:100%;margin:0;color:#ccc;font-size:20px;";
|
||||
xButton.innerHTML = "X";
|
||||
xButton.onclick = function () {
|
||||
setupWalletElement.remove();
|
||||
dummyRow.remove();
|
||||
};
|
||||
|
||||
setupWalletElement.appendChild(span);
|
||||
setupWalletElement.appendChild(xButton);
|
||||
|
||||
resultsElement.insertBefore(setupWalletElement, resultsElement.firstChild);
|
||||
|
||||
// Dummy row for padding
|
||||
var dummyRow = document.createElement('div');
|
||||
dummyRow.classList.add("row");
|
||||
dummyRow.style = "height:15px;";
|
||||
resultsElement.insertBefore(dummyRow, resultsElement.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
function maybeAddLogInButton() {
|
||||
if (!userIsLoggedIn) {
|
||||
var resultsElement = document.getElementById('results');
|
||||
|
@ -149,7 +192,7 @@
|
|||
var dropDownElement = document.getElementById('user-dropdown');
|
||||
purchasesElement.id = "purchasesButton";
|
||||
purchasesElement.setAttribute('href', "#");
|
||||
purchasesElement.innerHTML = "MY PURCHASES";
|
||||
purchasesElement.innerHTML = "My Purchases";
|
||||
// FRONTEND WEBDEV RANT: The username dropdown should REALLY not be programmed to be on the same
|
||||
// line as the search bar, overlaid on top of the search bar, floated right, and then relatively bumped up using "top:-50px".
|
||||
purchasesElement.style = "height:100%;margin-top:18px;font-weight:bold;float:right;margin-right:" + (dropDownElement.offsetWidth + 30) +
|
||||
|
@ -164,12 +207,34 @@
|
|||
}
|
||||
}
|
||||
|
||||
function changeDropdownMenu() {
|
||||
var logInOrOutButton = document.createElement('a');
|
||||
logInOrOutButton.id = "logInOrOutButton";
|
||||
logInOrOutButton.setAttribute('href', "#");
|
||||
logInOrOutButton.innerHTML = userIsLoggedIn ? "Log Out" : "Log In";
|
||||
logInOrOutButton.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "LOGIN"
|
||||
}));
|
||||
};
|
||||
|
||||
$($('.dropdown-menu').find('li')[0]).append(logInOrOutButton);
|
||||
|
||||
$('a[href="/marketplace?view=mine"]').each(function () {
|
||||
$(this).attr('href', '#');
|
||||
$(this).on('click', function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "MY_ITEMS"
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function buyButtonClicked(id, name, author, price, href) {
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "CHECKOUT",
|
||||
itemId: id,
|
||||
itemName: name,
|
||||
itemAuthor: author,
|
||||
itemPrice: price ? parseInt(price, 10) : 0,
|
||||
itemHref: href
|
||||
}));
|
||||
|
@ -235,9 +300,13 @@
|
|||
}
|
||||
|
||||
function injectHiFiCode() {
|
||||
if (confirmAllPurchases) {
|
||||
if (!$('body').hasClass("code-injected") && confirmAllPurchases) {
|
||||
|
||||
$('body').addClass("code-injected");
|
||||
|
||||
maybeAddLogInButton();
|
||||
maybeAddSetupWalletButton();
|
||||
changeDropdownMenu();
|
||||
|
||||
var target = document.getElementById('templated-items');
|
||||
// MutationObserver is necessary because the DOM is populated after the page is loaded.
|
||||
|
@ -260,9 +329,13 @@
|
|||
}
|
||||
|
||||
function injectHiFiItemPageCode() {
|
||||
if (confirmAllPurchases) {
|
||||
if (!$('body').hasClass("code-injected") && confirmAllPurchases) {
|
||||
|
||||
$('body').addClass("code-injected");
|
||||
|
||||
maybeAddLogInButton();
|
||||
maybeAddSetupWalletButton();
|
||||
changeDropdownMenu();
|
||||
|
||||
var purchaseButton = $('#side-info').find('.btn').first();
|
||||
|
||||
|
@ -551,7 +624,8 @@
|
|||
if (parsedJsonMessage.type === "marketplaces") {
|
||||
if (parsedJsonMessage.action === "commerceSetting") {
|
||||
confirmAllPurchases = !!parsedJsonMessage.data.commerceMode;
|
||||
userIsLoggedIn = !!parsedJsonMessage.data.userIsLoggedIn
|
||||
userIsLoggedIn = !!parsedJsonMessage.data.userIsLoggedIn;
|
||||
walletNeedsSetup = !!parsedJsonMessage.data.walletNeedsSetup;
|
||||
injectCode();
|
||||
}
|
||||
}
|
||||
|
@ -567,4 +641,5 @@
|
|||
|
||||
// Load / unload.
|
||||
window.addEventListener("load", onLoad); // More robust to Web site issues than using $(document).ready().
|
||||
window.addEventListener("page:change", onLoad); // Triggered after Marketplace HTML is changed
|
||||
}());
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
var MARKETPLACE_URL_INITIAL = MARKETPLACE_URL + "?"; // Append "?" to signal injected script that it's the initial page.
|
||||
var MARKETPLACES_URL = Script.resolvePath("../html/marketplaces.html");
|
||||
var MARKETPLACES_INJECT_SCRIPT_URL = Script.resolvePath("../html/js/marketplacesInject.js");
|
||||
var MARKETPLACE_CHECKOUT_QML_PATH = Script.resourcesPath() + "qml/hifi/commerce/checkout/Checkout.qml";
|
||||
var MARKETPLACE_CHECKOUT_QML_PATH_BASE = "qml/hifi/commerce/checkout/Checkout.qml";
|
||||
var MARKETPLACE_CHECKOUT_QML_PATH = Script.resourcesPath() + MARKETPLACE_CHECKOUT_QML_PATH_BASE;
|
||||
var MARKETPLACE_PURCHASES_QML_PATH = Script.resourcesPath() + "qml/hifi/commerce/purchases/Purchases.qml";
|
||||
var MARKETPLACE_WALLET_QML_PATH = Script.resourcesPath() + "qml/hifi/commerce/wallet/Wallet.qml";
|
||||
var MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH = "commerce/inspectionCertificate/InspectionCertificate.qml";
|
||||
|
@ -60,6 +61,7 @@
|
|||
var onCommerceScreen = false;
|
||||
|
||||
var debugCheckout = false;
|
||||
var debugError = false;
|
||||
function showMarketplace() {
|
||||
if (!debugCheckout) {
|
||||
UserActivityLogger.openedMarketplace();
|
||||
|
@ -70,8 +72,7 @@
|
|||
method: 'updateCheckoutQML', params: {
|
||||
itemId: '0d90d21c-ce7a-4990-ad18-e9d2cf991027',
|
||||
itemName: 'Test Flaregun',
|
||||
itemAuthor: 'hifiDave',
|
||||
itemPrice: 17,
|
||||
itemPrice: (debugError ? 10 : 17),
|
||||
itemHref: 'http://mpassets.highfidelity.com/0d90d21c-ce7a-4990-ad18-e9d2cf991027-v1/flaregun.json',
|
||||
},
|
||||
canRezCertifiedItems: Entities.canRezCertified || Entities.canRezTmpCertified
|
||||
|
@ -106,8 +107,8 @@
|
|||
var referrerURL; // Used for updating Purchases QML
|
||||
var filterText; // Used for updating Purchases QML
|
||||
function onScreenChanged(type, url) {
|
||||
onMarketplaceScreen = type === "Web" && url === MARKETPLACE_URL_INITIAL;
|
||||
onCommerceScreen = type === "QML" && (url === MARKETPLACE_CHECKOUT_QML_PATH || url === MARKETPLACE_PURCHASES_QML_PATH || url.indexOf(MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH) !== -1);
|
||||
onMarketplaceScreen = type === "Web" && url.indexOf(MARKETPLACE_URL) !== -1;
|
||||
onCommerceScreen = type === "QML" && (url.indexOf(MARKETPLACE_CHECKOUT_QML_PATH_BASE) !== -1 || url === MARKETPLACE_PURCHASES_QML_PATH || url.indexOf(MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH) !== -1);
|
||||
wireEventBridge(onCommerceScreen);
|
||||
|
||||
if (url === MARKETPLACE_PURCHASES_QML_PATH) {
|
||||
|
@ -128,12 +129,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
function setCertificateInfo(currentEntityWithContextOverlay, itemMarketplaceId, closeGoesToPurchases) {
|
||||
function setCertificateInfo(currentEntityWithContextOverlay, itemMarketplaceId) {
|
||||
wireEventBridge(true);
|
||||
tablet.sendToQml({
|
||||
method: 'inspectionCertificate_setMarketplaceId',
|
||||
marketplaceId: itemMarketplaceId || Entities.getEntityProperties(currentEntityWithContextOverlay, ['marketplaceID']).marketplaceID,
|
||||
closeGoesToPurchases: closeGoesToPurchases
|
||||
marketplaceId: itemMarketplaceId || Entities.getEntityProperties(currentEntityWithContextOverlay, ['marketplaceID']).marketplaceID
|
||||
});
|
||||
// ZRF FIXME! Make a call to the endpoint to get item info instead of this silliness
|
||||
Script.setTimeout(function () {
|
||||
|
@ -203,7 +203,8 @@
|
|||
action: "commerceSetting",
|
||||
data: {
|
||||
commerceMode: Settings.getValue("commerce", false),
|
||||
userIsLoggedIn: Account.loggedIn
|
||||
userIsLoggedIn: Account.loggedIn,
|
||||
walletNeedsSetup: Wallet.walletStatus === 1
|
||||
}
|
||||
}));
|
||||
} else if (parsedJsonMessage.type === "PURCHASES") {
|
||||
|
@ -212,6 +213,16 @@
|
|||
tablet.pushOntoStack(MARKETPLACE_PURCHASES_QML_PATH);
|
||||
} else if (parsedJsonMessage.type === "LOGIN") {
|
||||
openLoginWindow();
|
||||
} else if (parsedJsonMessage.type === "WALLET_SETUP") {
|
||||
tablet.pushOntoStack(MARKETPLACE_WALLET_QML_PATH);
|
||||
} else if (parsedJsonMessage.type === "MY_ITEMS") {
|
||||
referrerURL = MARKETPLACE_URL_INITIAL;
|
||||
filterText = "";
|
||||
tablet.pushOntoStack(MARKETPLACE_PURCHASES_QML_PATH);
|
||||
wireEventBridge(true);
|
||||
tablet.sendToQml({
|
||||
method: 'purchases_showMyItems'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -325,36 +336,26 @@
|
|||
case 'maybeEnableHmdPreview':
|
||||
Menu.setIsOptionChecked("Disable Preview", isHmdPreviewDisabled);
|
||||
break;
|
||||
case 'purchases_getIsFirstUse':
|
||||
tablet.sendToQml({
|
||||
method: 'purchases_getIsFirstUseResult',
|
||||
isFirstUseOfPurchases: Settings.getValue("isFirstUseOfPurchases", true)
|
||||
});
|
||||
break;
|
||||
case 'purchases_setIsFirstUse':
|
||||
Settings.setValue("isFirstUseOfPurchases", false);
|
||||
break;
|
||||
case 'purchases_openGoTo':
|
||||
tablet.loadQMLSource("TabletAddressDialog.qml");
|
||||
break;
|
||||
case 'purchases_itemCertificateClicked':
|
||||
tablet.loadQMLSource("../commerce/inspectionCertificate/InspectionCertificate.qml");
|
||||
setCertificateInfo("", message.itemMarketplaceId, true);
|
||||
setCertificateInfo("", message.itemMarketplaceId);
|
||||
break;
|
||||
case 'inspectionCertificate_closeClicked':
|
||||
if (message.closeGoesToPurchases) {
|
||||
referrerURL = MARKETPLACE_URL_INITIAL;
|
||||
filterText = "";
|
||||
tablet.pushOntoStack(MARKETPLACE_PURCHASES_QML_PATH);
|
||||
} else {
|
||||
tablet.gotoHomeScreen();
|
||||
}
|
||||
tablet.gotoHomeScreen();
|
||||
break;
|
||||
case 'inspectionCertificate_showInMarketplaceClicked':
|
||||
tablet.gotoWebScreen(MARKETPLACE_URL + '/items/' + message.itemId, MARKETPLACES_INJECT_SCRIPT_URL);
|
||||
break;
|
||||
case 'header_myItemsClicked':
|
||||
tablet.gotoWebScreen(MARKETPLACE_URL + '?view=mine', MARKETPLACES_INJECT_SCRIPT_URL);
|
||||
referrerURL = MARKETPLACE_URL_INITIAL;
|
||||
filterText = "";
|
||||
tablet.pushOntoStack(MARKETPLACE_PURCHASES_QML_PATH);
|
||||
wireEventBridge(true);
|
||||
tablet.sendToQml({
|
||||
method: 'purchases_showMyItems'
|
||||
});
|
||||
break;
|
||||
default:
|
||||
print('Unrecognized message from Checkout.qml or Purchases.qml: ' + JSON.stringify(message));
|
||||
|
|
Loading…
Reference in a new issue