mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
Merge pull request #12108 from zfox23/commerce_pagination
Commerce: Support pagination at History endpoint; improve Purchases scrolling
This commit is contained in:
commit
928e3d2ef7
6 changed files with 137 additions and 44 deletions
|
@ -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;
|
||||
|
|
|
@ -25,8 +25,12 @@ 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;
|
||||
property var pagesAlreadyAdded: new Array();
|
||||
|
||||
Connections {
|
||||
target: Commerce;
|
||||
|
@ -36,32 +40,86 @@ 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') {
|
||||
var currentPage = parseInt(result.current_page);
|
||||
|
||||
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();
|
||||
|
||||
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 {
|
||||
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();
|
||||
}
|
||||
calculatePendingAndInvalidated();
|
||||
}
|
||||
}
|
||||
refreshTimer.start();
|
||||
|
||||
// Only auto-refresh if the user hasn't scrolled
|
||||
// and there is more data to grab
|
||||
if (transactionHistory.atYBeginning && !root.noMoreHistoryData) {
|
||||
refreshTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,9 +192,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 +226,12 @@ Item {
|
|||
id: refreshTimer;
|
||||
interval: 4000;
|
||||
onTriggered: {
|
||||
console.log("Refreshing Wallet Home...");
|
||||
Commerce.balance();
|
||||
Commerce.history();
|
||||
if (transactionHistory.atYBeginning) {
|
||||
console.log("Refreshing 1st Page of Recent Activity...");
|
||||
root.historyRequestPending = true;
|
||||
Commerce.balance();
|
||||
Commerce.history(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,7 +306,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 +429,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...");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,11 +72,16 @@ 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, const QString& success, const QString& fail, QJsonObject& requestParams) {
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
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::keysQuery(const QString& endpoint, const QString& success, const QString& fail) {
|
||||
QJsonObject 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) {
|
||||
|
@ -169,6 +174,7 @@ void Ledger::historySuccess(QNetworkReply& reply) {
|
|||
QJsonObject newDataData;
|
||||
newDataData["history"] = newHistoryArray;
|
||||
newData["data"] = newDataData;
|
||||
newData["current_page"] = data["current_page"].toInt();
|
||||
emit historyResult(newData);
|
||||
}
|
||||
|
||||
|
@ -176,8 +182,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 int& pageNumber) {
|
||||
QJsonObject params;
|
||||
params["per_page"] = 100;
|
||||
params["page"] = pageNumber;
|
||||
keysQuery("history", "historySuccess", "historyFailure", params);
|
||||
}
|
||||
|
||||
// The api/failResponse is called just for the side effect of logging.
|
||||
|
|
|
@ -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 int& pageNumber);
|
||||
void account();
|
||||
void reset();
|
||||
void updateLocation(const QString& asset_id, const QString location, const bool controlledFailure = false);
|
||||
|
@ -79,6 +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, 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);
|
||||
};
|
||||
|
|
|
@ -96,12 +96,12 @@ void QmlCommerce::inventory() {
|
|||
}
|
||||
}
|
||||
|
||||
void QmlCommerce::history() {
|
||||
void QmlCommerce::history(const int& pageNumber) {
|
||||
auto ledger = DependencyManager::get<Ledger>();
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
QStringList cachedPublicKeys = wallet->listPublicKeys();
|
||||
if (!cachedPublicKeys.isEmpty()) {
|
||||
ledger->history(cachedPublicKeys);
|
||||
ledger->history(cachedPublicKeys, pageNumber);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 int& pageNumber);
|
||||
Q_INVOKABLE void generateKeyPair();
|
||||
Q_INVOKABLE void reset();
|
||||
Q_INVOKABLE void resetLocalWalletOnly();
|
||||
|
|
Loading…
Reference in a new issue