From 10d494b51de4243b1258625933c4ca6a507c26da Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 4 Jan 2018 12:32:30 -0800 Subject: [PATCH 01/10] Pagination for Recent Activity --- .../qml/hifi/commerce/purchases/Purchases.qml | 7 ++ .../qml/hifi/commerce/wallet/WalletHome.qml | 87 +++++++++++++------ interface/src/commerce/Ledger.cpp | 19 ++-- interface/src/commerce/Ledger.h | 4 +- interface/src/commerce/QmlCommerce.cpp | 4 +- interface/src/commerce/QmlCommerce.h | 2 +- 6 files changed, 82 insertions(+), 41 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index de66be4a88..068403e098 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -472,6 +472,13 @@ Rectangle { } } } + + onAtYEndChanged: { + if (purchasesContentsList.atYEnd) { + console.log("User scrolled to the bottom of 'My Purchases'."); + // Grab next page of results and append to model + } + } } Item { diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml index 42ee44d584..16ad999441 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml @@ -25,8 +25,11 @@ Item { HifiConstants { id: hifi; } id: root; - property bool historyReceived: false; + property bool initialHistoryReceived: false; + property bool historyRequestPending: true; + property bool noMoreHistoryData: false; property int pendingCount: 0; + property int currentHistoryPage: 1; Connections { target: Commerce; @@ -36,32 +39,50 @@ Item { } onHistoryResult : { - historyReceived = true; - if (result.status === 'success') { - var sameItemCount = 0; - tempTransactionHistoryModel.clear(); - - tempTransactionHistoryModel.append(result.data.history); - - for (var i = 0; i < tempTransactionHistoryModel.count; i++) { - if (!transactionHistoryModel.get(i)) { - sameItemCount = -1; - break; - } else if (tempTransactionHistoryModel.get(i).transaction_type === transactionHistoryModel.get(i).transaction_type && - tempTransactionHistoryModel.get(i).text === transactionHistoryModel.get(i).text) { - sameItemCount++; - } - } + root.initialHistoryReceived = true; + root.historyRequestPending = false; - if (sameItemCount !== tempTransactionHistoryModel.count) { - transactionHistoryModel.clear(); + if (result.status === 'success') { + if (result.data.history.length === 0) { + root.noMoreHistoryData = true; + } else if (root.currentHistoryPage === 1) { + var sameItemCount = 0; + tempTransactionHistoryModel.clear(); + + tempTransactionHistoryModel.append(result.data.history); + for (var i = 0; i < tempTransactionHistoryModel.count; i++) { - transactionHistoryModel.append(tempTransactionHistoryModel.get(i)); + if (!transactionHistoryModel.get(i)) { + sameItemCount = -1; + break; + } else if (tempTransactionHistoryModel.get(i).transaction_type === transactionHistoryModel.get(i).transaction_type && + tempTransactionHistoryModel.get(i).text === transactionHistoryModel.get(i).text) { + sameItemCount++; + } + } + + if (sameItemCount !== tempTransactionHistoryModel.count) { + transactionHistoryModel.clear(); + for (var i = 0; i < tempTransactionHistoryModel.count; i++) { + transactionHistoryModel.append(tempTransactionHistoryModel.get(i)); + } + calculatePendingAndInvalidated(); + } + } else { + // This prevents data from being displayed out-of-order, + // but may also result in missing pages of data when scrolling quickly... + if (root.currentHistoryPage === result.current_page) { + transactionHistoryModel.append(result.data.history); + calculatePendingAndInvalidated(); } - calculatePendingAndInvalidated(); } } - refreshTimer.start(); + + // Only auto-refresh if the user hasn't scrolled + // and there is more data to grab + if (root.currentHistoryPage === 1 && !root.noMoreHistoryData) { + refreshTimer.start(); + } } } @@ -134,9 +155,13 @@ Item { onVisibleChanged: { if (visible) { - historyReceived = false; + transactionHistoryModel.clear(); Commerce.balance(); - Commerce.history(); + initialHistoryReceived = false; + root.currentHistoryPage = 1; + root.noMoreHistoryData = false; + root.historyRequestPending = true; + Commerce.history(root.currentHistoryPage); } else { refreshTimer.stop(); } @@ -164,9 +189,10 @@ Item { id: refreshTimer; interval: 4000; onTriggered: { - console.log("Refreshing Wallet Home..."); + console.log("Refreshing 1st Page of Recent Activity..."); + root.historyRequestPending = true; Commerce.balance(); - Commerce.history(); + Commerce.history(1); } } @@ -241,7 +267,7 @@ Item { anchors.right: parent.right; Item { - visible: transactionHistoryModel.count === 0 && root.historyReceived; + visible: transactionHistoryModel.count === 0 && root.initialHistoryReceived; anchors.centerIn: parent; width: parent.width - 12; height: parent.height; @@ -364,7 +390,12 @@ Item { onAtYEndChanged: { if (transactionHistory.atYEnd) { console.log("User scrolled to the bottom of 'Recent Activity'."); - // Grab next page of results and append to model + if (!root.historyRequestPending && !root.noMoreHistoryData) { + // Grab next page of results and append to model + root.historyRequestPending = true; + Commerce.history(++root.currentHistoryPage); + console.log("Fetching Page " + root.currentHistoryPage + " of Recent Activity..."); + } } } } diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index d7d36dabf6..b2ac92e85a 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -72,11 +72,11 @@ void Ledger::signedSend(const QString& propertyName, const QByteArray& text, con send(endpoint, success, fail, QNetworkAccessManager::PutOperation, AccountManagerAuth::Required, request); } -void Ledger::keysQuery(const QString& endpoint, const QString& success, const QString& fail) { +void Ledger::keysQuery(const QString& endpoint, QJsonObject& requestParams, const QString& success, const QString& fail) { auto wallet = DependencyManager::get(); - QJsonObject request; - request["public_keys"] = QJsonArray::fromStringList(wallet->listPublicKeys()); - send(endpoint, success, fail, QNetworkAccessManager::PostOperation, AccountManagerAuth::Required, request); + requestParams["public_keys"] = QJsonArray::fromStringList(wallet->listPublicKeys()); + + send(endpoint, success, fail, QNetworkAccessManager::PostOperation, AccountManagerAuth::Required, requestParams); } void Ledger::buy(const QString& hfc_key, int cost, const QString& asset_id, const QString& inventory_key, const bool controlled_failure) { @@ -104,11 +104,11 @@ bool Ledger::receiveAt(const QString& hfc_key, const QString& old_key) { } void Ledger::balance(const QStringList& keys) { - keysQuery("balance", "balanceSuccess", "balanceFailure"); + keysQuery("balance", QJsonObject(), "balanceSuccess", "balanceFailure"); } void Ledger::inventory(const QStringList& keys) { - keysQuery("inventory", "inventorySuccess", "inventoryFailure"); + keysQuery("inventory", QJsonObject(), "inventorySuccess", "inventoryFailure"); } QString amountString(const QString& label, const QString&color, const QJsonValue& moneyValue, const QJsonValue& certsValue) { @@ -176,8 +176,11 @@ void Ledger::historyFailure(QNetworkReply& reply) { failResponse("history", reply); } -void Ledger::history(const QStringList& keys) { - keysQuery("history", "historySuccess", "historyFailure"); +void Ledger::history(const QStringList& keys, const QString& pageNumber) { + QJsonObject params; + params["per_page"] = 7; + params["page"] = pageNumber; + keysQuery("history", params, "historySuccess", "historyFailure"); } // The api/failResponse is called just for the side effect of logging. diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index 42eb0ffc49..db3d1f064a 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -29,7 +29,7 @@ public: bool receiveAt(const QString& hfc_key, const QString& old_key); void balance(const QStringList& keys); void inventory(const QStringList& keys); - void history(const QStringList& keys); + void history(const QStringList& keys, const QString& pageNumber); void account(); void reset(); void updateLocation(const QString& asset_id, const QString location, const bool controlledFailure = false); @@ -79,7 +79,7 @@ private: QJsonObject apiResponse(const QString& label, QNetworkReply& reply); QJsonObject failResponse(const QString& label, QNetworkReply& reply); void send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request); - void keysQuery(const QString& endpoint, const QString& success, const QString& fail); + void keysQuery(const QString& endpoint, QJsonObject& extraRequestParams, const QString& success, const QString& fail); void signedSend(const QString& propertyName, const QByteArray& text, const QString& key, const QString& endpoint, const QString& success, const QString& fail, const bool controlled_failure = false); }; diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 62e87f9c66..36608fe0a6 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -96,12 +96,12 @@ void QmlCommerce::inventory() { } } -void QmlCommerce::history() { +void QmlCommerce::history(const QString& pageNumber) { auto ledger = DependencyManager::get(); auto wallet = DependencyManager::get(); QStringList cachedPublicKeys = wallet->listPublicKeys(); if (!cachedPublicKeys.isEmpty()) { - ledger->history(cachedPublicKeys); + ledger->history(cachedPublicKeys, pageNumber); } } diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index c53e73d565..88223aacb0 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -60,7 +60,7 @@ protected: Q_INVOKABLE void buy(const QString& assetId, int cost, const bool controlledFailure = false); Q_INVOKABLE void balance(); Q_INVOKABLE void inventory(); - Q_INVOKABLE void history(); + Q_INVOKABLE void history(const QString& pageNumber); Q_INVOKABLE void generateKeyPair(); Q_INVOKABLE void reset(); Q_INVOKABLE void resetLocalWalletOnly(); From 14447c26a0c69be9505391ea5903778777322bfa Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 4 Jan 2018 13:47:31 -0800 Subject: [PATCH 02/10] Prevent visual data loss --- .../qml/hifi/commerce/wallet/WalletHome.qml | 54 ++++++++++++++++--- interface/src/commerce/Ledger.cpp | 1 + 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml index 16ad999441..1fd304246f 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml @@ -30,6 +30,7 @@ Item { property bool noMoreHistoryData: false; property int pendingCount: 0; property int currentHistoryPage: 1; + property var pagesAlreadyAdded: new Array(); Connections { target: Commerce; @@ -43,6 +44,8 @@ Item { root.historyRequestPending = false; if (result.status === 'success') { + var currentPage = parseInt(result.current_page); + if (result.data.history.length === 0) { root.noMoreHistoryData = true; } else if (root.currentHistoryPage === 1) { @@ -69,10 +72,43 @@ Item { calculatePendingAndInvalidated(); } } else { - // This prevents data from being displayed out-of-order, - // but may also result in missing pages of data when scrolling quickly... - if (root.currentHistoryPage === result.current_page) { - transactionHistoryModel.append(result.data.history); + if (root.pagesAlreadyAdded.indexOf(currentPage) !== -1) { + console.log("Page " + currentPage + " of history has already been added to the list."); + } else { + // First, add the history result to a temporary model + tempTransactionHistoryModel.clear(); + tempTransactionHistoryModel.append(result.data.history); + + // Make a note that we've already added this page to the model... + root.pagesAlreadyAdded.push(currentPage); + + var insertionIndex = 0; + // If there's nothing in the model right now, we don't need to modify insertionIndex. + if (transactionHistoryModel.count !== 0) { + var currentIteratorPage; + // Search through the whole transactionHistoryModel and look for the insertion point. + // The insertion point is found when the result page from the server is less than + // the page that the current item came from, OR when we've reached the end of the whole model. + for (var i = 0; i < transactionHistoryModel.count; i++) { + currentIteratorPage = transactionHistoryModel.get(i).resultIsFromPage; + + if (currentPage < currentIteratorPage) { + insertionIndex = i; + break; + } else if (i === transactionHistoryModel.count - 1) { + insertionIndex = i + 1; + break; + } + } + } + + // Go through the results we just got back from the server, setting the "resultIsFromPage" + // property of those results and adding them to the main model. + for (var i = 0; i < tempTransactionHistoryModel.count; i++) { + tempTransactionHistoryModel.setProperty(i, "resultIsFromPage", currentPage); + transactionHistoryModel.insert(i + insertionIndex, tempTransactionHistoryModel.get(i)) + } + calculatePendingAndInvalidated(); } } @@ -189,10 +225,12 @@ Item { id: refreshTimer; interval: 4000; onTriggered: { - console.log("Refreshing 1st Page of Recent Activity..."); - root.historyRequestPending = true; - Commerce.balance(); - Commerce.history(1); + if (root.currentHistoryPage === 1) { + console.log("Refreshing 1st Page of Recent Activity..."); + root.historyRequestPending = true; + Commerce.balance(); + Commerce.history(1); + } } } diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index b2ac92e85a..41ef1a1932 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -169,6 +169,7 @@ void Ledger::historySuccess(QNetworkReply& reply) { QJsonObject newDataData; newDataData["history"] = newHistoryArray; newData["data"] = newDataData; + newData["current_page"] = data["current_page"].toInt(); emit historyResult(newData); } From 4232bc02004e5e9e4e93dc4255e351fc46c7304b Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 4 Jan 2018 14:42:05 -0800 Subject: [PATCH 03/10] Bump per_page to 100 --- interface/src/commerce/Ledger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index 41ef1a1932..5d765e2c32 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -179,7 +179,7 @@ void Ledger::historyFailure(QNetworkReply& reply) { void Ledger::history(const QStringList& keys, const QString& pageNumber) { QJsonObject params; - params["per_page"] = 7; + params["per_page"] = 100; params["page"] = pageNumber; keysQuery("history", params, "historySuccess", "historyFailure"); } From 4612ef3d7cdf5a1d32fcb3f5f3576e34b1cfdb6b Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 4 Jan 2018 15:41:01 -0800 Subject: [PATCH 04/10] Use atYBeginning --- interface/resources/qml/hifi/commerce/wallet/WalletHome.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml index 1fd304246f..af708b4031 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml @@ -116,7 +116,7 @@ Item { // Only auto-refresh if the user hasn't scrolled // and there is more data to grab - if (root.currentHistoryPage === 1 && !root.noMoreHistoryData) { + if (transactionHistory.atYBeginning && !root.noMoreHistoryData) { refreshTimer.start(); } } @@ -225,7 +225,7 @@ Item { id: refreshTimer; interval: 4000; onTriggered: { - if (root.currentHistoryPage === 1) { + if (transactionHistory.atYBeginning) { console.log("Refreshing 1st Page of Recent Activity..."); root.historyRequestPending = true; Commerce.balance(); From cdd62c7119b161d46e09d0385c0adc0c6ef8bbe5 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 8 Jan 2018 11:29:41 -0800 Subject: [PATCH 05/10] I don't think auto-refresh and pagination of inventory is possible --- .../qml/hifi/commerce/checkout/Checkout.qml | 4 +- .../qml/hifi/commerce/purchases/Purchases.qml | 173 +++++++++++++----- interface/src/commerce/Ledger.cpp | 7 +- interface/src/commerce/Ledger.h | 2 +- interface/src/commerce/QmlCommerce.cpp | 4 +- interface/src/commerce/QmlCommerce.h | 2 +- 6 files changed, 134 insertions(+), 58 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 4de09c1bf3..d7c86566a4 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -117,7 +117,7 @@ Rectangle { } onItemIdChanged: { - Commerce.inventory(); + Commerce.inventory(1); itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg"; } @@ -945,7 +945,7 @@ Rectangle { } root.balanceReceived = false; root.purchasesReceived = false; - Commerce.inventory(); + Commerce.inventory(1); Commerce.balance(); } diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 068403e098..25aeadaa80 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -30,12 +30,16 @@ Rectangle { property string activeView: "initialize"; property string referrerURL: ""; property bool securityImageResultReceived: false; - property bool purchasesReceived: false; property bool punctuationMode: false; property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified(); - property bool pendingInventoryReply: true; property bool isShowingMyItems: false; property bool isDebuggingFirstUseTutorial: false; + property bool initialPurchasesReceived: false; + property bool pendingPurchasesReply: true; + property bool noMorePurchasesData: false; + property var pagesAlreadyAdded: new Array(); + property int currentPurchasesPage: 1; + // Style color: hifi.colors.white; Connections { @@ -61,7 +65,9 @@ Rectangle { root.activeView = "firstUseTutorial"; } else if (!Settings.getValue("isFirstUseOfPurchases", true) && root.activeView === "initialize") { root.activeView = "purchasesMain"; - Commerce.inventory(); + root.initialPurchasesReceived = false; + root.pendingPurchasesReply = true; + Commerce.inventory(1); } } else { console.log("ERROR in Purchases.qml: Unknown wallet status: " + walletStatus); @@ -77,35 +83,87 @@ Rectangle { } onInventoryResult: { - purchasesReceived = true; - - if (root.pendingInventoryReply) { - inventoryTimer.start(); - } - if (result.status !== 'success') { console.log("Failed to get purchases", result.message); } else { - var inventoryResult = processInventoryResult(result.data.assets); + var currentPage = parseInt(result.current_page); - purchasesModel.clear(); - purchasesModel.append(inventoryResult); + console.log("ZRF length: " + result.data.assets.length + " page: " + currentPage); + if (result.data.assets.length === 0) { + root.noMorePurchasesData = true; + } else if (root.currentPurchasesPage === 1) { + var purchasesResult = processPurchasesResult(result.data.assets); - if (previousPurchasesModel.count !== 0) { - checkIfAnyItemStatusChanged(); - } else { - // Fill statusChanged default value - // Not doing this results in the default being true... - for (var i = 0; i < purchasesModel.count; i++) { - purchasesModel.setProperty(i, "statusChanged", false); + purchasesModel.clear(); + purchasesModel.append(purchasesResult); + + if (previousPurchasesModel.count !== 0) { + checkIfAnyItemStatusChanged(); + } else { + // Fill statusChanged default value + // Not doing this results in the default being true... + for (var i = 0; i < purchasesModel.count; i++) { + purchasesModel.setProperty(i, "statusChanged", false); + } } + previousPurchasesModel.append(purchasesResult); + + buildFilteredPurchasesModel(); + } else { + // First, add the purchases result to a temporary model + tempPurchasesModel.clear(); + tempPurchasesModel.append(processPurchasesResult(result.data.assets)); + + // Make a note that we've already added this page to the model... + root.pagesAlreadyAdded.push(currentPage); + + var insertionIndex = 0; + // If there's nothing in the model right now, we don't need to modify insertionIndex. + if (purchasesModel.count !== 0) { + var currentIteratorPage; + // Search through the whole purchasesModel and look for the insertion point. + // The insertion point is found when the result page from the server is less than + // the page that the current item came from, OR when we've reached the end of the whole model. + for (var i = 0; i < purchasesModel.count; i++) { + currentIteratorPage = purchasesModel.get(i).resultIsFromPage; + + if (currentPage < currentIteratorPage) { + insertionIndex = i; + break; + } else if (i === purchasesModel.count - 1) { + insertionIndex = i + 1; + break; + } + } + } + + // Go through the results we just got back from the server, setting the "resultIsFromPage" + // property of those results and adding them to the main model. + for (var i = 0; i < tempPurchasesModel.count; i++) { + tempPurchasesModel.setProperty(i, "resultIsFromPage", currentPage); + purchasesModel.insert(i + insertionIndex, tempPurchasesModel.get(i)) + } + + buildFilteredPurchasesModel(); } - previousPurchasesModel.append(inventoryResult); - - buildFilteredPurchasesModel(); } + + root.pendingPurchasesReply = false; - root.pendingInventoryReply = false; + if (filteredPurchasesModel.count === 0 && !root.noMorePurchasesData) { + root.initialPurchasesReceived = false; + root.pendingPurchasesReply = true; + Commerce.inventory(++root.currentPurchasesPage); + console.log("Fetching Page " + root.currentPurchasesPage + " of Purchases..."); + // Only auto-refresh if the user hasn't scrolled + // and there is more data to grab + } else { + root.initialPurchasesReceived = true; + } + + if (purchasesContentsList.atYBeginning && !root.noMorePurchasesData) { + purchasesTimer.start(); + } } } @@ -197,7 +255,8 @@ Rectangle { Component.onCompleted: { securityImageResultReceived = false; - purchasesReceived = false; + root.initialPurchasesReceived = false; + root.pendingPurchasesReply = true; Commerce.getWalletStatus(); } } @@ -255,7 +314,9 @@ Rectangle { case 'tutorial_finished': Settings.setValue("isFirstUseOfPurchases", false); root.activeView = "purchasesMain"; - Commerce.inventory(); + root.initialPurchasesReceived = false; + root.pendingPurchasesReply = true; + Commerce.inventory(1); break; } } @@ -318,6 +379,12 @@ Rectangle { onTextChanged: { buildFilteredPurchasesModel(); + if (filteredPurchasesModel.count === 0 && !root.noMorePurchasesData) { + root.initialPurchasesReceived = false; + root.pendingPurchasesReply = true; + Commerce.inventory(++root.currentPurchasesPage); + console.log("Fetching Page " + root.currentPurchasesPage + " of Purchases..."); + } } onAccepted: { @@ -476,14 +543,19 @@ Rectangle { onAtYEndChanged: { if (purchasesContentsList.atYEnd) { console.log("User scrolled to the bottom of 'My Purchases'."); - // Grab next page of results and append to model + if (!root.pendingPurchasesReply && !root.noMorePurchasesData) { + // Grab next page of results and append to model + root.pendingPurchasesReply = true; + Commerce.inventory(++root.currentPurchasesPage); + console.log("Fetching Page " + root.currentPurchasesPage + " of Purchases..."); + } } } } Item { id: noItemsAlertContainer; - visible: !purchasesContentsList.visible && root.purchasesReceived && root.isShowingMyItems && filterBar.text === ""; + visible: !purchasesContentsList.visible && root.initialPurchasesReceived && root.isShowingMyItems && filterBar.text === "" && root.noMorePurchasesData; anchors.top: filterBarContainer.bottom; anchors.topMargin: 12; anchors.left: parent.left; @@ -529,7 +601,7 @@ Rectangle { Item { id: noPurchasesAlertContainer; - visible: !purchasesContentsList.visible && root.purchasesReceived && !root.isShowingMyItems && filterBar.text === ""; + visible: !purchasesContentsList.visible && root.initialPurchasesReceived && !root.isShowingMyItems && filterBar.text === "" && root.noMorePurchasesData; anchors.top: filterBarContainer.bottom; anchors.topMargin: 12; anchors.left: parent.left; @@ -590,19 +662,19 @@ Rectangle { onVisibleChanged: { if (!visible) { - inventoryTimer.stop(); + purchasesTimer.stop(); } } Timer { - id: inventoryTimer; + id: purchasesTimer; interval: 4000; // Change this back to 90000 after demo //interval: 90000; onTriggered: { - if (root.activeView === "purchasesMain" && !root.pendingInventoryReply) { - console.log("Refreshing Purchases..."); - root.pendingInventoryReply = true; - Commerce.inventory(); + if (root.activeView === "purchasesMain" && purchasesContentsList.atYBeginning && !root.pendingPurchasesReply && !root.noMorePurchasesData) { + console.log("Refreshing 1st Page of Purchases..."); + root.pendingPurchasesReply = true; + Commerce.inventory(1); } } } @@ -611,15 +683,15 @@ Rectangle { // FUNCTION DEFINITIONS START // - function processInventoryResult(inventory) { - for (var i = 0; i < inventory.length; i++) { - if (inventory[i].status.length > 1) { - console.log("WARNING: Inventory result index " + i + " has a status of length >1!") + function processPurchasesResult(purchases) { + for (var i = 0; i < purchases.length; i++) { + if (purchases[i].status.length > 1) { + console.log("WARNING: Purchases result index " + i + " has a status of length >1!") } - inventory[i].status = inventory[i].status[0]; - inventory[i].categories = inventory[i].categories.join(';'); + purchases[i].status = purchases[i].status[0]; + purchases[i].categories = purchases[i].categories.join(';'); } - return inventory; + return purchases; } function populateDisplayedItemCounts() { @@ -660,17 +732,18 @@ Rectangle { } } - for (var i = 0; i < tempPurchasesModel.count; i++) { - if (!filteredPurchasesModel.get(i)) { - sameItemCount = -1; - break; - } else if (tempPurchasesModel.get(i).itemId === filteredPurchasesModel.get(i).itemId && - tempPurchasesModel.get(i).edition_number === filteredPurchasesModel.get(i).edition_number && - tempPurchasesModel.get(i).status === filteredPurchasesModel.get(i).status) { - sameItemCount++; + if (tempPurchasesModel.count === 0 || filteredPurchasesModel.count === 0) { + sameItemCount = -1; + } else { + for (var i = 0; i < tempPurchasesModel.count; i++) { + if (tempPurchasesModel.get(i).itemId === filteredPurchasesModel.get(i).itemId && + tempPurchasesModel.get(i).edition_number === filteredPurchasesModel.get(i).edition_number && + tempPurchasesModel.get(i).status === filteredPurchasesModel.get(i).status) { + sameItemCount++; + } } } - + if (sameItemCount !== tempPurchasesModel.count) { filteredPurchasesModel.clear(); for (var i = 0; i < tempPurchasesModel.count; i++) { diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index 5d765e2c32..f02a70376d 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -107,8 +107,11 @@ void Ledger::balance(const QStringList& keys) { keysQuery("balance", QJsonObject(), "balanceSuccess", "balanceFailure"); } -void Ledger::inventory(const QStringList& keys) { - keysQuery("inventory", QJsonObject(), "inventorySuccess", "inventoryFailure"); +void Ledger::inventory(const QStringList& keys, const QString& pageNumber) { + QJsonObject params; + params["per_page"] = 1; + params["page"] = pageNumber; + keysQuery("inventory", params, "inventorySuccess", "inventoryFailure"); } QString amountString(const QString& label, const QString&color, const QJsonValue& moneyValue, const QJsonValue& certsValue) { diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index db3d1f064a..6770e47e6e 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -28,7 +28,7 @@ public: void buy(const QString& hfc_key, int cost, const QString& asset_id, const QString& inventory_key, const bool controlled_failure = false); bool receiveAt(const QString& hfc_key, const QString& old_key); void balance(const QStringList& keys); - void inventory(const QStringList& keys); + void inventory(const QStringList& keys, const QString& pageNumber); void history(const QStringList& keys, const QString& pageNumber); void account(); void reset(); diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 36608fe0a6..354335668f 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -87,12 +87,12 @@ void QmlCommerce::balance() { } } -void QmlCommerce::inventory() { +void QmlCommerce::inventory(const QString& pageNumber) { auto ledger = DependencyManager::get(); auto wallet = DependencyManager::get(); QStringList cachedPublicKeys = wallet->listPublicKeys(); if (!cachedPublicKeys.isEmpty()) { - ledger->inventory(cachedPublicKeys); + ledger->inventory(cachedPublicKeys, pageNumber); } } diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index 88223aacb0..891c838b68 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -59,7 +59,7 @@ protected: Q_INVOKABLE void buy(const QString& assetId, int cost, const bool controlledFailure = false); Q_INVOKABLE void balance(); - Q_INVOKABLE void inventory(); + Q_INVOKABLE void inventory(const QString& pageNumber); Q_INVOKABLE void history(const QString& pageNumber); Q_INVOKABLE void generateKeyPair(); Q_INVOKABLE void reset(); From dcfceab0789d5b7379f200452cfc5adbe923b7a1 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 8 Jan 2018 12:03:56 -0800 Subject: [PATCH 06/10] Remove all work done on paginating purchases --- .../qml/hifi/commerce/checkout/Checkout.qml | 4 +- .../qml/hifi/commerce/purchases/Purchases.qml | 176 +++++------------- interface/src/commerce/Ledger.cpp | 7 +- interface/src/commerce/Ledger.h | 2 +- interface/src/commerce/QmlCommerce.cpp | 4 +- interface/src/commerce/QmlCommerce.h | 2 +- 6 files changed, 56 insertions(+), 139 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index d7c86566a4..4de09c1bf3 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -117,7 +117,7 @@ Rectangle { } onItemIdChanged: { - Commerce.inventory(1); + Commerce.inventory(); itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg"; } @@ -945,7 +945,7 @@ Rectangle { } root.balanceReceived = false; root.purchasesReceived = false; - Commerce.inventory(1); + Commerce.inventory(); Commerce.balance(); } diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 25aeadaa80..de66be4a88 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -30,16 +30,12 @@ Rectangle { property string activeView: "initialize"; property string referrerURL: ""; property bool securityImageResultReceived: false; + property bool purchasesReceived: false; property bool punctuationMode: false; property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified(); + property bool pendingInventoryReply: true; property bool isShowingMyItems: false; property bool isDebuggingFirstUseTutorial: false; - property bool initialPurchasesReceived: false; - property bool pendingPurchasesReply: true; - property bool noMorePurchasesData: false; - property var pagesAlreadyAdded: new Array(); - property int currentPurchasesPage: 1; - // Style color: hifi.colors.white; Connections { @@ -65,9 +61,7 @@ Rectangle { root.activeView = "firstUseTutorial"; } else if (!Settings.getValue("isFirstUseOfPurchases", true) && root.activeView === "initialize") { root.activeView = "purchasesMain"; - root.initialPurchasesReceived = false; - root.pendingPurchasesReply = true; - Commerce.inventory(1); + Commerce.inventory(); } } else { console.log("ERROR in Purchases.qml: Unknown wallet status: " + walletStatus); @@ -83,87 +77,35 @@ Rectangle { } onInventoryResult: { + purchasesReceived = true; + + if (root.pendingInventoryReply) { + inventoryTimer.start(); + } + if (result.status !== 'success') { console.log("Failed to get purchases", result.message); } else { - var currentPage = parseInt(result.current_page); + var inventoryResult = processInventoryResult(result.data.assets); - console.log("ZRF length: " + result.data.assets.length + " page: " + currentPage); - if (result.data.assets.length === 0) { - root.noMorePurchasesData = true; - } else if (root.currentPurchasesPage === 1) { - var purchasesResult = processPurchasesResult(result.data.assets); + purchasesModel.clear(); + purchasesModel.append(inventoryResult); - purchasesModel.clear(); - purchasesModel.append(purchasesResult); - - if (previousPurchasesModel.count !== 0) { - checkIfAnyItemStatusChanged(); - } else { - // Fill statusChanged default value - // Not doing this results in the default being true... - for (var i = 0; i < purchasesModel.count; i++) { - purchasesModel.setProperty(i, "statusChanged", false); - } - } - previousPurchasesModel.append(purchasesResult); - - buildFilteredPurchasesModel(); + if (previousPurchasesModel.count !== 0) { + checkIfAnyItemStatusChanged(); } else { - // First, add the purchases result to a temporary model - tempPurchasesModel.clear(); - tempPurchasesModel.append(processPurchasesResult(result.data.assets)); - - // Make a note that we've already added this page to the model... - root.pagesAlreadyAdded.push(currentPage); - - var insertionIndex = 0; - // If there's nothing in the model right now, we don't need to modify insertionIndex. - if (purchasesModel.count !== 0) { - var currentIteratorPage; - // Search through the whole purchasesModel and look for the insertion point. - // The insertion point is found when the result page from the server is less than - // the page that the current item came from, OR when we've reached the end of the whole model. - for (var i = 0; i < purchasesModel.count; i++) { - currentIteratorPage = purchasesModel.get(i).resultIsFromPage; - - if (currentPage < currentIteratorPage) { - insertionIndex = i; - break; - } else if (i === purchasesModel.count - 1) { - insertionIndex = i + 1; - break; - } - } + // Fill statusChanged default value + // Not doing this results in the default being true... + for (var i = 0; i < purchasesModel.count; i++) { + purchasesModel.setProperty(i, "statusChanged", false); } - - // Go through the results we just got back from the server, setting the "resultIsFromPage" - // property of those results and adding them to the main model. - for (var i = 0; i < tempPurchasesModel.count; i++) { - tempPurchasesModel.setProperty(i, "resultIsFromPage", currentPage); - purchasesModel.insert(i + insertionIndex, tempPurchasesModel.get(i)) - } - - buildFilteredPurchasesModel(); } - } - - root.pendingPurchasesReply = false; + previousPurchasesModel.append(inventoryResult); - if (filteredPurchasesModel.count === 0 && !root.noMorePurchasesData) { - root.initialPurchasesReceived = false; - root.pendingPurchasesReply = true; - Commerce.inventory(++root.currentPurchasesPage); - console.log("Fetching Page " + root.currentPurchasesPage + " of Purchases..."); - // Only auto-refresh if the user hasn't scrolled - // and there is more data to grab - } else { - root.initialPurchasesReceived = true; - } - - if (purchasesContentsList.atYBeginning && !root.noMorePurchasesData) { - purchasesTimer.start(); + buildFilteredPurchasesModel(); } + + root.pendingInventoryReply = false; } } @@ -255,8 +197,7 @@ Rectangle { Component.onCompleted: { securityImageResultReceived = false; - root.initialPurchasesReceived = false; - root.pendingPurchasesReply = true; + purchasesReceived = false; Commerce.getWalletStatus(); } } @@ -314,9 +255,7 @@ Rectangle { case 'tutorial_finished': Settings.setValue("isFirstUseOfPurchases", false); root.activeView = "purchasesMain"; - root.initialPurchasesReceived = false; - root.pendingPurchasesReply = true; - Commerce.inventory(1); + Commerce.inventory(); break; } } @@ -379,12 +318,6 @@ Rectangle { onTextChanged: { buildFilteredPurchasesModel(); - if (filteredPurchasesModel.count === 0 && !root.noMorePurchasesData) { - root.initialPurchasesReceived = false; - root.pendingPurchasesReply = true; - Commerce.inventory(++root.currentPurchasesPage); - console.log("Fetching Page " + root.currentPurchasesPage + " of Purchases..."); - } } onAccepted: { @@ -539,23 +472,11 @@ Rectangle { } } } - - onAtYEndChanged: { - if (purchasesContentsList.atYEnd) { - console.log("User scrolled to the bottom of 'My Purchases'."); - if (!root.pendingPurchasesReply && !root.noMorePurchasesData) { - // Grab next page of results and append to model - root.pendingPurchasesReply = true; - Commerce.inventory(++root.currentPurchasesPage); - console.log("Fetching Page " + root.currentPurchasesPage + " of Purchases..."); - } - } - } } Item { id: noItemsAlertContainer; - visible: !purchasesContentsList.visible && root.initialPurchasesReceived && root.isShowingMyItems && filterBar.text === "" && root.noMorePurchasesData; + visible: !purchasesContentsList.visible && root.purchasesReceived && root.isShowingMyItems && filterBar.text === ""; anchors.top: filterBarContainer.bottom; anchors.topMargin: 12; anchors.left: parent.left; @@ -601,7 +522,7 @@ Rectangle { Item { id: noPurchasesAlertContainer; - visible: !purchasesContentsList.visible && root.initialPurchasesReceived && !root.isShowingMyItems && filterBar.text === "" && root.noMorePurchasesData; + visible: !purchasesContentsList.visible && root.purchasesReceived && !root.isShowingMyItems && filterBar.text === ""; anchors.top: filterBarContainer.bottom; anchors.topMargin: 12; anchors.left: parent.left; @@ -662,19 +583,19 @@ Rectangle { onVisibleChanged: { if (!visible) { - purchasesTimer.stop(); + inventoryTimer.stop(); } } Timer { - id: purchasesTimer; + id: inventoryTimer; interval: 4000; // Change this back to 90000 after demo //interval: 90000; onTriggered: { - if (root.activeView === "purchasesMain" && purchasesContentsList.atYBeginning && !root.pendingPurchasesReply && !root.noMorePurchasesData) { - console.log("Refreshing 1st Page of Purchases..."); - root.pendingPurchasesReply = true; - Commerce.inventory(1); + if (root.activeView === "purchasesMain" && !root.pendingInventoryReply) { + console.log("Refreshing Purchases..."); + root.pendingInventoryReply = true; + Commerce.inventory(); } } } @@ -683,15 +604,15 @@ Rectangle { // FUNCTION DEFINITIONS START // - function processPurchasesResult(purchases) { - for (var i = 0; i < purchases.length; i++) { - if (purchases[i].status.length > 1) { - console.log("WARNING: Purchases result index " + i + " has a status of length >1!") + function processInventoryResult(inventory) { + for (var i = 0; i < inventory.length; i++) { + if (inventory[i].status.length > 1) { + console.log("WARNING: Inventory result index " + i + " has a status of length >1!") } - purchases[i].status = purchases[i].status[0]; - purchases[i].categories = purchases[i].categories.join(';'); + inventory[i].status = inventory[i].status[0]; + inventory[i].categories = inventory[i].categories.join(';'); } - return purchases; + return inventory; } function populateDisplayedItemCounts() { @@ -732,18 +653,17 @@ Rectangle { } } - if (tempPurchasesModel.count === 0 || filteredPurchasesModel.count === 0) { - sameItemCount = -1; - } else { - for (var i = 0; i < tempPurchasesModel.count; i++) { - if (tempPurchasesModel.get(i).itemId === filteredPurchasesModel.get(i).itemId && - tempPurchasesModel.get(i).edition_number === filteredPurchasesModel.get(i).edition_number && - tempPurchasesModel.get(i).status === filteredPurchasesModel.get(i).status) { - sameItemCount++; - } + for (var i = 0; i < tempPurchasesModel.count; i++) { + if (!filteredPurchasesModel.get(i)) { + sameItemCount = -1; + break; + } else if (tempPurchasesModel.get(i).itemId === filteredPurchasesModel.get(i).itemId && + tempPurchasesModel.get(i).edition_number === filteredPurchasesModel.get(i).edition_number && + tempPurchasesModel.get(i).status === filteredPurchasesModel.get(i).status) { + sameItemCount++; } } - + if (sameItemCount !== tempPurchasesModel.count) { filteredPurchasesModel.clear(); for (var i = 0; i < tempPurchasesModel.count; i++) { diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index f02a70376d..5d765e2c32 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -107,11 +107,8 @@ void Ledger::balance(const QStringList& keys) { keysQuery("balance", QJsonObject(), "balanceSuccess", "balanceFailure"); } -void Ledger::inventory(const QStringList& keys, const QString& pageNumber) { - QJsonObject params; - params["per_page"] = 1; - params["page"] = pageNumber; - keysQuery("inventory", params, "inventorySuccess", "inventoryFailure"); +void Ledger::inventory(const QStringList& keys) { + keysQuery("inventory", QJsonObject(), "inventorySuccess", "inventoryFailure"); } QString amountString(const QString& label, const QString&color, const QJsonValue& moneyValue, const QJsonValue& certsValue) { diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index 6770e47e6e..db3d1f064a 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -28,7 +28,7 @@ public: void buy(const QString& hfc_key, int cost, const QString& asset_id, const QString& inventory_key, const bool controlled_failure = false); bool receiveAt(const QString& hfc_key, const QString& old_key); void balance(const QStringList& keys); - void inventory(const QStringList& keys, const QString& pageNumber); + void inventory(const QStringList& keys); void history(const QStringList& keys, const QString& pageNumber); void account(); void reset(); diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 354335668f..36608fe0a6 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -87,12 +87,12 @@ void QmlCommerce::balance() { } } -void QmlCommerce::inventory(const QString& pageNumber) { +void QmlCommerce::inventory() { auto ledger = DependencyManager::get(); auto wallet = DependencyManager::get(); QStringList cachedPublicKeys = wallet->listPublicKeys(); if (!cachedPublicKeys.isEmpty()) { - ledger->inventory(cachedPublicKeys, pageNumber); + ledger->inventory(cachedPublicKeys); } } diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index 891c838b68..88223aacb0 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -59,7 +59,7 @@ protected: Q_INVOKABLE void buy(const QString& assetId, int cost, const bool controlledFailure = false); Q_INVOKABLE void balance(); - Q_INVOKABLE void inventory(const QString& pageNumber); + Q_INVOKABLE void inventory(); Q_INVOKABLE void history(const QString& pageNumber); Q_INVOKABLE void generateKeyPair(); Q_INVOKABLE void reset(); From 611f25d542d4cf61f4e372f287700cfcede96046 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 8 Jan 2018 13:07:00 -0800 Subject: [PATCH 07/10] Improve scrolling thru My Purchases --- .../qml/hifi/commerce/purchases/Purchases.qml | 23 +++++++++++++++---- .../qml/hifi/commerce/wallet/WalletHome.qml | 1 + 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index de66be4a88..87b784bc4e 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -36,6 +36,7 @@ Rectangle { property bool pendingInventoryReply: true; property bool isShowingMyItems: false; property bool isDebuggingFirstUseTutorial: false; + property int pendingItemCount: 0; // Style color: hifi.colors.white; Connections { @@ -79,18 +80,22 @@ Rectangle { onInventoryResult: { purchasesReceived = true; - if (root.pendingInventoryReply) { - inventoryTimer.start(); - } - if (result.status !== 'success') { console.log("Failed to get purchases", result.message); - } else { + } else if (!purchasesContentsList.dragging) { // Don't modify the view if the user's scrolling var inventoryResult = processInventoryResult(result.data.assets); + var currentIndex = purchasesContentsList.currentIndex === -1 ? 0 : purchasesContentsList.currentIndex; purchasesModel.clear(); purchasesModel.append(inventoryResult); + root.pendingItemCount = 0; + for (var i = 0; i < purchasesModel.count; i++) { + if (purchasesModel.get(i).status === "pending") { + root.pendingItemCount++; + } + } + if (previousPurchasesModel.count !== 0) { checkIfAnyItemStatusChanged(); } else { @@ -103,6 +108,12 @@ Rectangle { previousPurchasesModel.append(inventoryResult); buildFilteredPurchasesModel(); + + purchasesContentsList.positionViewAtIndex(currentIndex, ListView.Beginning); + } + + if (root.pendingInventoryReply && root.pendingItemCount > 0) { + inventoryTimer.start(); } root.pendingInventoryReply = false; @@ -419,6 +430,8 @@ Rectangle { visible: (root.isShowingMyItems && filteredPurchasesModel.count !== 0) || (!root.isShowingMyItems && filteredPurchasesModel.count !== 0); clip: true; model: filteredPurchasesModel; + snapMode: ListView.SnapToItem; + highlightRangeMode: ListView.StrictlyEnforceRange; // Anchors anchors.top: root.canRezCertifiedItems ? separator.bottom : cantRezCertified.bottom; anchors.topMargin: 12; diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml index af708b4031..780e08caf8 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml @@ -48,6 +48,7 @@ Item { if (result.data.history.length === 0) { root.noMoreHistoryData = true; + console.log("No more data to retrieve from Commerce.history() endpoint.") } else if (root.currentHistoryPage === 1) { var sameItemCount = 0; tempTransactionHistoryModel.clear(); From 360a7cc4c68aed249457f1e654ac93f367dc1986 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 9 Jan 2018 11:08:18 -0800 Subject: [PATCH 08/10] CR feedback --- interface/src/commerce/Ledger.cpp | 10 +++++----- interface/src/commerce/Ledger.h | 4 ++-- interface/src/commerce/QmlCommerce.cpp | 2 +- interface/src/commerce/QmlCommerce.h | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index 5d765e2c32..d2ce28d2ea 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -72,7 +72,7 @@ void Ledger::signedSend(const QString& propertyName, const QByteArray& text, con send(endpoint, success, fail, QNetworkAccessManager::PutOperation, AccountManagerAuth::Required, request); } -void Ledger::keysQuery(const QString& endpoint, QJsonObject& requestParams, const QString& success, const QString& fail) { +void Ledger::keysQuery(const QString& endpoint, const QString& success, const QString& fail, QJsonObject& requestParams) { auto wallet = DependencyManager::get(); requestParams["public_keys"] = QJsonArray::fromStringList(wallet->listPublicKeys()); @@ -104,11 +104,11 @@ bool Ledger::receiveAt(const QString& hfc_key, const QString& old_key) { } void Ledger::balance(const QStringList& keys) { - keysQuery("balance", QJsonObject(), "balanceSuccess", "balanceFailure"); + keysQuery("balance", "balanceSuccess", "balanceFailure"); } void Ledger::inventory(const QStringList& keys) { - keysQuery("inventory", QJsonObject(), "inventorySuccess", "inventoryFailure"); + keysQuery("inventory", "inventorySuccess", "inventoryFailure"); } QString amountString(const QString& label, const QString&color, const QJsonValue& moneyValue, const QJsonValue& certsValue) { @@ -177,11 +177,11 @@ void Ledger::historyFailure(QNetworkReply& reply) { failResponse("history", reply); } -void Ledger::history(const QStringList& keys, const QString& pageNumber) { +void Ledger::history(const QStringList& keys, const int& pageNumber) { QJsonObject params; params["per_page"] = 100; params["page"] = pageNumber; - keysQuery("history", params, "historySuccess", "historyFailure"); + keysQuery("history", "historySuccess", "historyFailure", params); } // The api/failResponse is called just for the side effect of logging. diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index db3d1f064a..95329842cc 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -29,7 +29,7 @@ public: bool receiveAt(const QString& hfc_key, const QString& old_key); void balance(const QStringList& keys); void inventory(const QStringList& keys); - void history(const QStringList& keys, const QString& pageNumber); + void history(const QStringList& keys, const int& pageNumber); void account(); void reset(); void updateLocation(const QString& asset_id, const QString location, const bool controlledFailure = false); @@ -79,7 +79,7 @@ private: QJsonObject apiResponse(const QString& label, QNetworkReply& reply); QJsonObject failResponse(const QString& label, QNetworkReply& reply); void send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request); - void keysQuery(const QString& endpoint, QJsonObject& extraRequestParams, const QString& success, const QString& fail); + void keysQuery(const QString& endpoint, const QString& success, const QString& fail, QJsonObject& extraRequestParams = QJsonObject()); void signedSend(const QString& propertyName, const QByteArray& text, const QString& key, const QString& endpoint, const QString& success, const QString& fail, const bool controlled_failure = false); }; diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 36608fe0a6..320c7e041c 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -96,7 +96,7 @@ void QmlCommerce::inventory() { } } -void QmlCommerce::history(const QString& pageNumber) { +void QmlCommerce::history(const int& pageNumber) { auto ledger = DependencyManager::get(); auto wallet = DependencyManager::get(); QStringList cachedPublicKeys = wallet->listPublicKeys(); diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index 88223aacb0..f2e6c82021 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -60,7 +60,7 @@ protected: Q_INVOKABLE void buy(const QString& assetId, int cost, const bool controlledFailure = false); Q_INVOKABLE void balance(); Q_INVOKABLE void inventory(); - Q_INVOKABLE void history(const QString& pageNumber); + Q_INVOKABLE void history(const int& pageNumber); Q_INVOKABLE void generateKeyPair(); Q_INVOKABLE void reset(); Q_INVOKABLE void resetLocalWalletOnly(); From d31dec7acb5e1d81f1662a762bbd8794a1be876a Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 9 Jan 2018 12:41:56 -0800 Subject: [PATCH 09/10] Fix unix build errors --- interface/src/commerce/Ledger.cpp | 8 ++++++++ interface/src/commerce/Ledger.h | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index d2ce28d2ea..ba153c383d 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -79,6 +79,14 @@ void Ledger::keysQuery(const QString& endpoint, const QString& success, const QS send(endpoint, success, fail, QNetworkAccessManager::PostOperation, AccountManagerAuth::Required, requestParams); } +void Ledger::keysQuery(const QString& endpoint, const QString& success, const QString& fail) { + auto wallet = DependencyManager::get(); + QJsonObject requestParams; + requestParams["public_keys"] = QJsonArray::fromStringList(wallet->listPublicKeys()); + + send(endpoint, success, fail, QNetworkAccessManager::PostOperation, AccountManagerAuth::Required, requestParams); +} + void Ledger::buy(const QString& hfc_key, int cost, const QString& asset_id, const QString& inventory_key, const bool controlled_failure) { QJsonObject transaction; transaction["hfc_key"] = hfc_key; diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index 95329842cc..5d90aa0808 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -79,7 +79,8 @@ private: QJsonObject apiResponse(const QString& label, QNetworkReply& reply); QJsonObject failResponse(const QString& label, QNetworkReply& reply); void send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request); - void keysQuery(const QString& endpoint, const QString& success, const QString& fail, QJsonObject& extraRequestParams = QJsonObject()); + void keysQuery(const QString& endpoint, const QString& success, const QString& fail, QJsonObject& extraRequestParams); + void keysQuery(const QString& endpoint, const QString& success, const QString& fail); void signedSend(const QString& propertyName, const QByteArray& text, const QString& key, const QString& endpoint, const QString& success, const QString& fail, const bool controlled_failure = false); }; From edf25c3e4e319b3c05742edd4d04acbd667727f7 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 9 Jan 2018 14:14:54 -0800 Subject: [PATCH 10/10] Remove code duplication... --- interface/src/commerce/Ledger.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index ba153c383d..51658ddef8 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -80,11 +80,8 @@ void Ledger::keysQuery(const QString& endpoint, const QString& success, const QS } void Ledger::keysQuery(const QString& endpoint, const QString& success, const QString& fail) { - auto wallet = DependencyManager::get(); QJsonObject requestParams; - requestParams["public_keys"] = QJsonArray::fromStringList(wallet->listPublicKeys()); - - send(endpoint, success, fail, QNetworkAccessManager::PostOperation, AccountManagerAuth::Required, requestParams); + keysQuery(endpoint, success, fail, requestParams); } void Ledger::buy(const QString& hfc_key, int cost, const QString& asset_id, const QString& inventory_key, const bool controlled_failure) {