checkpoint

This commit is contained in:
howard-stearns 2018-05-30 17:09:13 -07:00
parent a84829392f
commit bdd38cef7a
7 changed files with 124 additions and 59 deletions

View file

@ -0,0 +1,39 @@
//
// RootHttpRequest.qml
// qml/hifi
//
// Create an item of this in the ROOT qml to be able to make http requests.
// Used by PSFListModel.qml
//
// Created by Howard Stearns on 5/29/2018
// Copyright 2018 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
Item {
property var httpCalls: ({});
property var httpCounter: 0;
// Public function for initiating an http request.
// REQUIRES parent to be root to have sendToScript!
function request(options, callback) {
console.debug('HttpRequest', JSON.stringify(options));
httpCalls[httpCounter] = callback;
var message = {method: 'http.request', params: options, id: httpCounter++, jsonrpc: "2.0"};
parent.sendToScript(message);
}
// REQUIRES that parent/root handle http.response message.method in fromScript, by calling this function.
function handleHttpResponse(message) {
var callback = httpCalls[message.id]; // FIXME: as different top level tablet apps gets loaded, the id repeats. We should drop old app callbacks without warning.
if (!callback) {
console.warn('No callback for', JSON.stringify(message));
return;
}
delete httpCalls[message.id];
console.debug('HttpRequest response', JSON.stringify(message));
callback(message.error, message.response);
}
}

View file

@ -37,6 +37,8 @@ Item {
property string assetName: "";
property string assetCertID: "";
property string sendingPubliclyEffectImage;
property var http;
property var listModelName;
// This object is always used in a popup or full-screen Wallet section.
// This MouseArea is used to prevent a user from being
@ -393,7 +395,8 @@ Item {
HifiModels.PSFListModel {
id: connectionsModel;
http: root.parent; // Misuse of "root" in this file!
http: root.http;
listModelName: root.listModelName;
endpoint: "/api/v1/users?filter=connections";
itemsPerPage: 8;
processPage: function (data) {

View file

@ -21,6 +21,7 @@ import "../wallet" as HifiWallet
import "../common" as HifiCommerceCommon
import "../inspectionCertificate" as HifiInspectionCertificate
import "../common/sendAsset" as HifiSendAsset
import "../.." as HifiCommon
// references XXX from root context
@ -81,7 +82,7 @@ Rectangle {
}
onInventoryResult: {
purchasesModel.pageRetrieved(result);
purchasesModel.handlePage(result.status !== "success" && result.message, result);
}
onAvailableUpdatesResult: {
@ -145,8 +146,14 @@ Rectangle {
}
}
HifiCommon.RootHttpRequest {
id: http;
}
HifiSendAsset.SendAsset {
id: sendAsset;
http: http;
listModelName: "Gift Connections";
z: 998;
visible: root.activeView === "giftAsset";
anchors.fill: parent;
@ -547,9 +554,10 @@ Rectangle {
HifiModels.PSFListModel {
id: purchasesModel;
itemsPerPage: 6;
itemsPerPage: 3;
getPage: function() {
getPage: function () {
console.log('HRS FIXME Purchases getPage', root.isShowingMyItems, filterBar.primaryFilter_filterName, purchasesModel.currentPageToRetrieve, purchasesModel.itemsPerPage);
Commerce.inventory(
root.isShowingMyItems ? "proofs" : "purchased",
filterBar.primaryFilter_filterName.toLowerCase(),
@ -557,10 +565,24 @@ Rectangle {
purchasesModel.itemsPerPage
);
}
pageRetrieved: function(result) {
purchasesReceived = true;
processPage: function(data) {
purchasesReceived = true; // HRS FIXME?
data.assets.forEach(function (item) {
if (item.status.length > 1) { console.warn("Unrecognized inventory status", item); }
item.status = item.status[0];
item.categories = item.categories.join(';');
item.cardBackVisible = false;
item.isInstalled = root.installedApps.indexOf(item.id) > -1;
item.wornEntityID = '';
// HRS FIXME updateable
});
// HRS FIXME purchaess_updateWearables
// HRS FIXME populateDisplayedItemCounts
// HRS FIXME sortByDate
return data.assets;
var processedInventory = processInventoryResult(result.data.assets);
/*
var processedInventory = processInventoryResult(data.assets);
if (purchasesModel.processResult(result.status, processedInventory)) {
var currentId;
@ -592,6 +614,7 @@ Rectangle {
// the most recent purchases on the 1st page)
//sortByDate();
}
*/
}
}
@ -970,7 +993,7 @@ Rectangle {
// FUNCTION DEFINITIONS START
//
function processInventoryResult(inventory) {
function processInventoryResult(inventory) { // HRS FIXME remove
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!")
@ -1087,6 +1110,9 @@ Rectangle {
case 'updateWearables':
updateCurrentlyWornWearables(message.wornWearables);
break;
case 'http.response':
http.handleHttpResponse(message);
break;
default:
console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message));
}

View file

@ -19,6 +19,7 @@ import "../../../controls-uit" as HifiControlsUit
import "../../../controls" as HifiControls
import "../common" as HifiCommerceCommon
import "../common/sendAsset"
import "../.." as HifiCommon
Rectangle {
HifiConstants { id: hifi; }
@ -343,8 +344,14 @@ Rectangle {
}
}
HifiCommon.RootHttpRequest {
id: http;
}
SendAsset {
id: sendMoney;
http: http;
listModelName: "Send Money Connections";
z: 997;
visible: root.activeView === "sendMoney";
anchors.fill: parent;
@ -762,38 +769,22 @@ Rectangle {
// NOP
break;
case 'updateConnections':
console.log('Wallet.qml updateConnections');// HRS FIXME
sendMoney.updateConnections(message.connections);
break;
case 'selectRecipient':
case 'updateSelectedRecipientUsername':
console.log('Wallet.qml updateSelectedRecipientUsername'); // HRS FIXME
sendMoney.fromScript(message);
break;
case 'http.response':
handleHttpResponse(message);
http.handleHttpResponse(message);
break;
default:
console.log('Unrecognized message from wallet.js:', JSON.stringify(message));
}
}
signal sendToScript(var message);
property var httpCalls: ({});
property var httpCounter: 0;
function request(options, callback) {
console.debug('HRS FIXME Wallet request', JSON.stringify(options));
httpCalls[httpCounter] = callback;
var message = {method: 'http.request', params: options, id: httpCounter++, jsonrpc: "2.0"};
sendToScript(message);
}
function handleHttpResponse(message) {
var callback = httpCalls[message.id]; // FIXME: as different top level tablet apps gets loaded, the id repeats. We should drop old app callbacks without warning.
if (!callback) {
console.warn('No callback for', JSON.stringify(message));
return;
}
delete httpCalls[message.id];
console.log('HRS FIXME QML handling of', JSON.stringify(message));
callback(message.error, message.response);
}
// generateUUID() taken from:
// https://stackoverflow.com/a/8809472

View file

@ -211,16 +211,15 @@ Item {
HifiModels.PSFListModel {
id: transactionHistoryModel;
listModelName: "transaction history";
itemsPerPage: 100;
listModelName: "transaction history"; // For debugging. Alternatively, we could specify endpoint for that purpose, even though it's not used directly.
itemsPerPage: 6;
getPage: function () {
console.log('HRS FIXME WalletHome getPage', transactionHistoryModel.currentPageToRetrieve, transactionHistoryModel.itemsPerPage);
console.debug('WalletHome getPage', transactionHistoryModel.currentPageToRetrieve);
Commerce.history(transactionHistoryModel.currentPageToRetrieve, transactionHistoryModel.itemsPerPage);
}
processPage: function (data) {
console.log('HRS FIXME WalletHome processPage', JSON.stringify(data));
var result, pending;
console.debug('WalletHome processPage', JSON.stringify(data));
var result, pending; // Set up or get the accumulator for pending.
if (transactionHistoryModel.currentPageToRetrieve == 1) {
pending = {transaction_type: "pendingCount", count: 0};
result = [pending];
@ -228,6 +227,8 @@ Item {
pending = transactionHistoryModel.get(0);
result = [];
}
// Either add to pending, or to result.
data.history.forEach(function (item) {
if (item.status === 'pending') {
pending.count++;

View file

@ -18,7 +18,7 @@
import QtQuick 2.7
Item {
id: root;
// Used when printing debug statements
property string listModelName: endpoint;
@ -28,9 +28,14 @@ Item {
property string sortKey;
property string searchFilter: "";
property string tagsFilter;
onEndpointChanged: getFirstPage();
onSortKeyChanged: getFirstPage();
// QML fires the following changed handlers even when first instantiating the Item. So we need a guard against firing them too early.
property bool initialized: false;
Component.onCompleted: initialized = true;
onEndpointChanged: if (initialized) { getFirstPage(); }
onSortKeyChanged: if (initialized) { getFirstPage(); }
onSearchFilterChanged: {
if (!initialized) { return; }
if (searchItemTest) {
var filteredCopy = applySearchItemTest(copyOfItems);
finalModel.clear();
@ -39,11 +44,11 @@ Item {
getFirstPage();
}
}
onTagsFilterChanged: getFirstPage();
onTagsFilterChanged: if (initialized) { getFirstPage(); }
property int itemsPerPage: 100;
// If the endpoint doesn't do search, tags, sort, these functions can be supplied to do it here.
property var searchItemTest: nil;
property var searchItemTest: null;
property var copyOfItems: [];
// State.
@ -67,10 +72,10 @@ Item {
// Check consistency and call processPage.
function handlePage(error, response) {
var processed;
console.log("HRS FIXME got", endpoint, error, JSON.stringify(response));
console.debug('handlePage', listModelName, error, JSON.stringify(response));
function fail(message) {
console.warn("Warning", listModelName, JSON.stringify(message));
current_page_to_retrieve = -1;
currentPageToRetrieve = -1;
requestPending = false;
delayedClear = false;
}
@ -105,9 +110,9 @@ Item {
}
// Override either http or getPage.
property var http: null; // An Item that has a request function.
property var http; // An Item that has a request function.
property var getPage: function () { // Any override MUST call handlePage(), above, even if results empty.
if (!http) { return console.warn("Neither http nor getPage was set in", listModelName); }
if (!http) { return console.warn("Neither http nor getPage was set for", listModelName); }
var url = /^\//.test(endpoint) ? (Account.metaverseServerURL + endpoint) : endpoint;
var parameters = [
// FIXME: handle sort, search, tag parameters
@ -116,7 +121,7 @@ Item {
];
var parametersSeparator = /\?/.test(url) ? '&' : '?';
url = url + parametersSeparator + parameters.join('&');
console.log("HRS FIXME requesting", url);
console.debug('getPage', listModelName);
http.request({uri: url}, handlePage);
}
@ -141,8 +146,8 @@ Item {
if (requestPending || currentPageToRetrieve < 0) {
return;
}
console.log("HRS FIXME Fetching Page " + currentPageToRetrieve + " of " + listModelName + "...");
currentPageToRetrieve++;
console.debug("getNextPage", listModelName, currentPageToRetrieve);
requestPending = true;
getPage();
}

View file

@ -22,7 +22,8 @@
// So, this script does two things:
// 1. Allows any root .qml to signal sendToScript({id: aString, method: 'http.request', params: byNameOptions})
// We will then asynchonously call fromScript({id: theSameString, method: 'http.response', error: errorOrFalsey, response: body})
// on that root object.
// on that root object.
// RootHttpRequest.qml does this.
// 2. If the uri used (computed from byNameOptions, see request.js) begins with '/', we will:
// a. Prepend Account.metaverseServerUR.
// b. Use the appropriate auth.
@ -30,20 +31,19 @@
var request = Script.require('request').request;
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
function fromQml(message) { // messages are {id, method, params}, like json-rpc. See also sendToQml.
switch (message.method) {
case 'http.request':
request(message.params, function (error, response) {
console.log('HRS FIXME request-service got', JSON.stringify(error), JSON.stringify(response));
tablet.sendToQml({
id: message.id,
method: 'http.response',
error: error, // Alas, this isn't always a JSON-RPC conforming error object.
response: response,
jsonrpc: '2.0'
});
});
break;
}
switch (message.method) {
case 'http.request':
request(message.params, function (error, response) {
tablet.sendToQml({
id: message.id,
method: 'http.response',
error: error, // Alas, this isn't always a JSON-RPC conforming error object.
response: response,
jsonrpc: '2.0'
});
});
break;
}
}
tablet.fromQml.connect(fromQml);
Script.scriptEnding.connect(function () { tablet.fromQml.disconnect(fromQml); });