From 3eb70a76177f3e7f453ee01b4ee87612365d97db Mon Sep 17 00:00:00 2001 From: Nex-Pro Date: Sat, 3 Nov 2018 16:08:53 +0000 Subject: [PATCH 01/13] Change to English spelling of 'declination' Addressed other minor typos. NB: Searched all sources in the project for the call and it is only found in this file. --- libraries/graphics/src/graphics/Stage.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/graphics/src/graphics/Stage.cpp b/libraries/graphics/src/graphics/Stage.cpp index 312ece6889..21929a61dd 100644 --- a/libraries/graphics/src/graphics/Stage.cpp +++ b/libraries/graphics/src/graphics/Stage.cpp @@ -223,8 +223,8 @@ void SunSkyStage::setSunDirection(const Vec3& direction) { } } -// THe sun declinaison calculus is taken from https://en.wikipedia.org/wiki/Position_of_the_Sun -double evalSunDeclinaison(double dayNumber) { +// The sun declination calculus is taken from https://en.wikipedia.org/wiki/Position_of_the_Sun +double evalSunDeclination(double dayNumber) { return -(23.0 + 44.0/60.0)*cos(glm::radians((360.0/365.0)*(dayNumber + 10.0))); } @@ -235,8 +235,8 @@ void SunSkyStage::updateGraphicsObject() const { float sunLongitude = _earthSunModel.getLongitude() + (MAX_LONGITUDE * signedNormalizedDayTime); _earthSunModel.setSunLongitude(sunLongitude); - // And update the sunLAtitude as the declinaison depending of the time of the year - _earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime)); + // And update the sunLatitude as the declination depending of the time of the year + _earthSunModel.setSunLatitude(evalSunDeclination(_yearTime)); if (isSunModelEnabled()) { Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); From e52c7d9c850c26c2586816a6762ad613f6d65064 Mon Sep 17 00:00:00 2001 From: birarda Date: Mon, 19 Nov 2018 17:32:18 -0800 Subject: [PATCH 02/13] update the control packet types after removals --- tools/dissectors/1-hfudt.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/dissectors/1-hfudt.lua b/tools/dissectors/1-hfudt.lua index 9ad89462f9..3993b2d7a0 100644 --- a/tools/dissectors/1-hfudt.lua +++ b/tools/dissectors/1-hfudt.lua @@ -39,9 +39,9 @@ p_hfudt.fields = { local control_types = { [0] = { "ACK", "Acknowledgement" }, - [5] = { "Handshake", "Handshake" }, - [6] = { "HandshakeACK", "Acknowledgement of Handshake" }, - [8] = { "HandshakeRequest", "Request a Handshake" } + [1] = { "Handshake", "Handshake" }, + [2] = { "HandshakeACK", "Acknowledgement of Handshake" }, + [3] = { "HandshakeRequest", "Request a Handshake" } } local message_positions = { From 23857ea8c2f1dc98a1d9408afcb7242c2da3589c Mon Sep 17 00:00:00 2001 From: birarda Date: Mon, 19 Nov 2018 17:38:58 -0800 Subject: [PATCH 03/13] ensure packets are added to loss list after timeout --- libraries/networking/src/udt/SendQueue.cpp | 30 ++++++++++++++++++---- libraries/networking/src/udt/SendQueue.h | 4 +-- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index 9cba4970ac..3178217a36 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -134,6 +134,7 @@ void SendQueue::stop() { } int SendQueue::sendPacket(const Packet& packet) { + _lastPacketSentAt = std::chrono::high_resolution_clock::now(); return _socket->writeDatagram(packet.getData(), packet.getDataSize(), _destination); } @@ -501,12 +502,31 @@ bool SendQueue::isInactive(bool attemptedToSendPacket) { // We think the client is still waiting for data (based on the sequence number gap) // Let's wait either for a response from the client or until the estimated timeout // (plus the sync interval to allow the client to respond) has elapsed - auto waitDuration = std::chrono::microseconds(_estimatedTimeout + _syncInterval); - + + auto estimatedTimeout = std::chrono::microseconds(_estimatedTimeout); + + // cap our maximum estimated timeout to the already unreasonable 5 seconds + const auto MAXIMUM_ESTIMATED_TIMEOUT = std::chrono::seconds(5); + + if (estimatedTimeout > MAXIMUM_ESTIMATED_TIMEOUT) { + estimatedTimeout = MAXIMUM_ESTIMATED_TIMEOUT; + } + // use our condition_variable_any to wait - auto cvStatus = _emptyCondition.wait_for(locker, waitDuration); - - if (cvStatus == std::cv_status::timeout && (_packets.isEmpty() || isFlowWindowFull()) && _naks.isEmpty() + auto cvStatus = _emptyCondition.wait_for(locker, estimatedTimeout); + + // when we wake-up check if we're "stuck" either if we've slept for the estimated timeout + // or it has been that long since the last time we sent a packet + + // we are stuck if all of the following are true + // - there are no new packets to send or the flow window is full and we can't send any new packets + // - there are no packets to resend + // - the client has yet to ACK some sent packets + auto now = std::chrono::high_resolution_clock::now(); + + if ((cvStatus == std::cv_status::timeout || (now - _lastPacketSentAt > estimatedTimeout)) + && (_packets.isEmpty() || isFlowWindowFull()) + && _naks.isEmpty() && SequenceNumber(_lastACKSequenceNumber) < _currentSequenceNumber) { // after a timeout if we still have sent packets that the client hasn't ACKed we // add them to the loss list diff --git a/libraries/networking/src/udt/SendQueue.h b/libraries/networking/src/udt/SendQueue.h index 65b1b89c7e..c1faac3b22 100644 --- a/libraries/networking/src/udt/SendQueue.h +++ b/libraries/networking/src/udt/SendQueue.h @@ -68,7 +68,6 @@ public: void setPacketSendPeriod(int newPeriod) { _packetSendPeriod = newPeriod; } void setEstimatedTimeout(int estimatedTimeout) { _estimatedTimeout = estimatedTimeout; } - void setSyncInterval(int syncInterval) { _syncInterval = syncInterval; } public slots: void stop(); @@ -124,7 +123,6 @@ private: std::atomic _state { State::NotStarted }; std::atomic _estimatedTimeout { 0 }; // Estimated timeout, set from CC - std::atomic _syncInterval { udt::DEFAULT_SYN_INTERVAL_USECS }; // Sync interval, set from CC std::atomic _flowWindowSize { 0 }; // Flow control window size (number of packets that can be on wire) - set from CC @@ -140,6 +138,8 @@ private: std::condition_variable _handshakeACKCondition; std::condition_variable_any _emptyCondition; + + std::chrono::high_resolution_clock::time_point _lastPacketSentAt; }; } From db607e564ff3c4f2d199fd0bdbb991878a2a5e1e Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 20 Nov 2018 09:13:07 -0800 Subject: [PATCH 04/13] fixing keyboard mallets dimensions --- interface/src/ui/Keyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp index 6852691634..46a25a24a7 100644 --- a/interface/src/ui/Keyboard.cpp +++ b/interface/src/ui/Keyboard.cpp @@ -60,7 +60,7 @@ static const float MALLET_TOUCH_Y_OFFSET = 0.050f; static const float MALLET_Y_OFFSET = 0.160f; static const glm::quat MALLET_ROTATION_OFFSET{0.70710678f, 0.0f, -0.70710678f, 0.0f}; -static const glm::vec3 MALLET_MODEL_DIMENSIONS{0.03f, MALLET_LENGTH, 0.03f}; +static const glm::vec3 MALLET_MODEL_DIMENSIONS{0.01f, MALLET_LENGTH, 0.01f}; static const glm::vec3 MALLET_POSITION_OFFSET{0.0f, -MALLET_Y_OFFSET / 2.0f, 0.0f}; static const glm::vec3 MALLET_TIP_OFFSET{0.0f, MALLET_LENGTH - MALLET_TOUCH_Y_OFFSET, 0.0f}; From 87878cbdee6f09f4b43bb8fd9b08168675e6e4c9 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 20 Nov 2018 10:40:32 -0800 Subject: [PATCH 05/13] use -shared-libasan with clang whem memory debugging is enabled --- cmake/macros/MemoryDebugger.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/macros/MemoryDebugger.cmake b/cmake/macros/MemoryDebugger.cmake index ed80e03c6b..09716715f0 100644 --- a/cmake/macros/MemoryDebugger.cmake +++ b/cmake/macros/MemoryDebugger.cmake @@ -16,9 +16,9 @@ if (HIFI_MEMORY_DEBUGGING) if (UNIX) if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") # for clang on Linux - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") - SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -shared-libasan -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -shared-libasan -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -shared-libasan -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") else () # for gcc on Linux SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fsanitize=address -U_FORTIFY_SOURCE -fno-stack-protector -fno-omit-frame-pointer") From 43b9aa29bc285e6bacb6cce1f028c77e3cfcdf81 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 26 Nov 2018 12:37:11 -0800 Subject: [PATCH 06/13] Make vcpkg build default to home directory on mac --- prebuild.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/prebuild.py b/prebuild.py index dacc49a86e..b8cb2c96ae 100644 --- a/prebuild.py +++ b/prebuild.py @@ -83,12 +83,17 @@ class VcpkgRepo: self.sourcePortsPath = os.path.join(scriptPath, 'cmake', 'ports') # FIXME Revert to ports hash before release self.id = hashFolder(self.sourcePortsPath)[:8] + # OS dependent information + system = platform.system() if args.vcpkg_root is not None: print("override vcpkg path with " + args.vcpkg_root) self.path = args.vcpkg_root else: - defaultBasePath = os.path.join(tempfile.gettempdir(), 'hifi', 'vcpkg') + if 'Darwin' == system: + defaultBasePath = os.path.expanduser('~/hifi/vcpkg') + else: + defaultBasePath = os.path.join(tempfile.gettempdir(), 'hifi', 'vcpkg') basePath = os.getenv('HIFI_VCPKG_BASE', defaultBasePath) if (not os.path.isdir(basePath)): os.makedirs(basePath) @@ -101,8 +106,6 @@ class VcpkgRepo: self.tagContents = "{}_{}".format(self.id, self.version) print("prebuild path: " + self.path) - # OS dependent information - system = platform.system() if 'Windows' == system: self.exe = os.path.join(self.path, 'vcpkg.exe') self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-win32.tar.gz?versionId=YZYkDejDRk7L_hrK_WVFthWvisAhbDzZ' From 8df5db4239d9185e91d349d2805c41f28bdf2e9e Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 26 Nov 2018 13:26:17 -0800 Subject: [PATCH 07/13] Allow scripts to open SendAsset screen with pre-filled info --- .../commerce/common/sendAsset/SendAsset.qml | 59 ++++++++++++++----- scripts/system/commerce/wallet.js | 5 ++ 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index d6378f82ac..2a5211d174 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -39,7 +39,7 @@ Item { property string sendingPubliclyEffectImage; property var http; property var listModelName; - property var keyboardContainer: nil; + property var keyboardContainer; // This object is always used in a popup or full-screen Wallet section. // This MouseArea is used to prevent a user from being @@ -405,7 +405,7 @@ Item { HifiModels.PSFListModel { id: connectionsModel; http: root.http; - listModelName: root.listModelName; + listModelName: root.listModelName || ""; endpoint: "/api/v1/users?filter=connections"; itemsPerPage: 9; listView: connectionsList; @@ -853,7 +853,7 @@ Item { id: sendAssetStep; z: 996; - property string referrer; // either "connections" or "nearby" + property string referrer; // either "connections", "nearby", or "payIn" property string selectedRecipientNodeID; property string selectedRecipientDisplayName; property string selectedRecipientUserName; @@ -931,6 +931,7 @@ Item { height: 35; width: 100; text: "CHANGE"; + visible: sendAssetStep.referrer !== "payIn"; onClicked: { if (sendAssetStep.referrer === "connections") { root.nextActiveView = "chooseRecipientConnection"; @@ -970,6 +971,7 @@ Item { HifiControlsUit.TextField { id: amountTextField; + readOnly: sendAssetStep.referrer === "payIn"; text: root.assetName === "" ? "" : "1"; colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; inputMethodHints: Qt.ImhDigitsOnly; @@ -980,8 +982,8 @@ Item { height: 50; // Style leftPermanentGlyph: hifi.glyphs.hfc; - activeFocusOnPress: true; - activeFocusOnTab: true; + activeFocusOnPress: !amountTextField.readOnly; + activeFocusOnTab: !amountTextField.readOnly; validator: IntValidator { bottom: 0; } @@ -1071,6 +1073,7 @@ Item { TextArea { id: optionalMessage; + readOnly: sendAssetStep.referrer === "payIn"; property int maximumLength: 72; property string previousText: text; placeholderText: "Optional Public Message (" + maximumLength + " character limit)"; @@ -1081,10 +1084,10 @@ Item { // Style background: Rectangle { anchors.fill: parent; - color: root.assetName === "" ? (optionalMessage.activeFocus ? hifi.colors.black : hifi.colors.baseGrayShadow) : - (optionalMessage.activeFocus ? "#EFEFEF" : "#EEEEEE"); - border.width: optionalMessage.activeFocus ? 1 : 0; - border.color: optionalMessage.activeFocus ? hifi.colors.primaryHighlight : hifi.colors.textFieldLightBackground; + color: root.assetName === "" ? (optionalMessage.activeFocus && !optionalMessage.readOnly ? hifi.colors.black : hifi.colors.baseGrayShadow) : + (optionalMessage.activeFocus && !optionalMessage.readOnly ? "#EFEFEF" : "#EEEEEE"); + border.width: optionalMessage.activeFocus && !optionalMessage.readOnly ? 1 : 0; + border.color: optionalMessage.activeFocus && !optionalMessage.readOnly ? hifi.colors.primaryHighlight : hifi.colors.textFieldLightBackground; } color: root.assetName === "" ? hifi.colors.white : hifi.colors.black; textFormat: TextEdit.PlainText; @@ -1205,8 +1208,12 @@ Item { width: 100; text: "CANCEL"; onClicked: { - resetSendAssetData(); - root.nextActiveView = "sendAssetHome"; + if (sendAssetStep.referrer === "payIn") { + sendToScript({method: "closeSendAsset"}); + } else { + resetSendAssetData(); + root.nextActiveView = "sendAssetHome"; + } } } @@ -1236,7 +1243,7 @@ Item { root.isCurrentlySendingAsset = true; amountTextField.focus = false; optionalMessage.focus = false; - if (sendAssetStep.referrer === "connections") { + if (sendAssetStep.referrer === "connections" || sendAssetStep.referrer === "payIn") { Commerce.transferAssetToUsername(sendAssetStep.selectedRecipientUserName, root.assetCertID, parseInt(amountTextField.text), @@ -1364,10 +1371,14 @@ Item { parent.text = hifi.glyphs.close; } onClicked: { - root.nextActiveView = "sendAssetHome"; - resetSendAssetData(); - if (root.assetName !== "") { - sendSignalToParent({method: "closeSendAsset"}); + if (sendAssetStep.referrer === "payIn") { + sendToScript({method: "closeSendAsset"}); + } else { + root.nextActiveView = "sendAssetHome"; + resetSendAssetData(); + if (root.assetName !== "") { + sendSignalToParent({method: "closeSendAsset"}); + } } } } @@ -1866,11 +1877,27 @@ Item { case 'updateSelectedRecipientUsername': sendAssetStep.selectedRecipientUserName = message.userName; break; + case 'updateSendAssetQML': + root.assetName = message.assetName || ""; + root.assetCertID = message.assetCertID || ""; + amountTextField.text = message.amount || 1; + sendAssetStep.referrer = "payIn"; + sendAssetStep.selectedRecipientNodeID = ""; + sendAssetStep.selectedRecipientDisplayName = 'Secure Payment'; + sendAssetStep.selectedRecipientUserName = message.username; + optionalMessage.text = message.message || "No Message Provided"; + + root.nextActiveView = "sendAssetStep"; + break; + case 'inspectionCertificate_resetCert': + // NOP + break; default: console.log('SendAsset: Unrecognized message from wallet.js'); } } signal sendSignalToParent(var msg); + signal sendToScript(var message); // // FUNCTION DEFINITIONS END // diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index 5e0cdbb94b..d5365133b6 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -539,6 +539,9 @@ function fromQml(message) { case 'http.request': // Handled elsewhere, don't log. break; + case 'closeSendAsset': + ui.close(); + break; default: print('wallet.js: Unrecognized message from QML'); } @@ -663,6 +666,7 @@ function uninstallMarketplaceItemTester() { var BUTTON_NAME = "INVENTORY"; var WALLET_QML_SOURCE = "hifi/commerce/wallet/Wallet.qml"; +var SENDASSET_QML_SOURCE = "hifi/commerce/common/sendAsset/SendAsset.qml"; var NOTIFICATION_POLL_TIMEOUT = 300000; var ui; function startup() { @@ -686,6 +690,7 @@ function startup() { buttonName: BUTTON_NAME, sortOrder: 10, home: WALLET_QML_SOURCE, + additionalAppScreens: SENDASSET_QML_SOURCE, onOpened: walletOpened, onClosed: walletClosed, onMessage: fromQml, From 31f7d747c8eb9b35e2f424dfbbef0578b636f436 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 26 Nov 2018 15:48:49 -0800 Subject: [PATCH 08/13] Bugfixes; enable purchase asset from marketplace screen raise --- .../qml/hifi/commerce/checkout/Checkout.qml | 51 +++++-- .../commerce/common/sendAsset/SendAsset.qml | 139 ++++++++++-------- scripts/system/html/js/marketplacesInject.js | 23 +-- scripts/system/marketplaces/marketplaces.js | 6 +- 4 files changed, 124 insertions(+), 95 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index c2a4d47992..6320cd1675 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -19,6 +19,7 @@ import controlsUit 1.0 as HifiControlsUit import "../../../controls" as HifiControls import "../wallet" as HifiWallet import "../common" as HifiCommerceCommon +import "../.." as HifiCommon // references XXX from root context @@ -31,6 +32,7 @@ Rectangle { property bool ownershipStatusReceived: false; property bool balanceReceived: false; property bool availableUpdatesReceived: false; + property bool itemInfoReceived: false; property string baseItemName: ""; property string itemName; property string itemId; @@ -181,11 +183,14 @@ Rectangle { onItemIdChanged: { root.ownershipStatusReceived = false; + root.itemInfoReceived = false; Commerce.alreadyOwned(root.itemId); root.availableUpdatesReceived = false; root.currentUpdatesPage = 1; Commerce.getAvailableUpdates(root.itemId); - itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg"; + + var MARKETPLACE_API_URL = Account.metaverseServerURL + "/api/v1/marketplace/items/"; + http.request({uri: MARKETPLACE_API_URL + root.itemId}, updateCheckoutQMLFromHTTP); } onItemTypeChanged: { @@ -279,6 +284,7 @@ Rectangle { ownershipStatusReceived = false; balanceReceived = false; availableUpdatesReceived = false; + itemInfoReceived = false; Commerce.getWalletStatus(); } } @@ -355,7 +361,7 @@ Rectangle { Rectangle { id: loading; z: 997; - visible: !root.ownershipStatusReceived || !root.balanceReceived || !root.availableUpdatesReceived; + visible: !root.ownershipStatusReceived || !root.balanceReceived || !root.availableUpdatesReceived || !root.itemInfoReceived; anchors.fill: parent; color: hifi.colors.white; @@ -1063,10 +1069,27 @@ Rectangle { } } } + + + HifiCommon.RootHttpRequest { + id: http; + } // // FUNCTION DEFINITIONS START // + + function updateCheckoutQMLFromHTTP(error, result) { + root.itemInfoReceived = true; + root.itemName = result.data.title; + root.itemPrice = result.data.cost; + root.itemHref = Account.metaverseServerURL + result.data.path; + root.itemAuthor = result.data.creator; + root.itemType = result.data.item_type || "unknown"; + itemPreviewImage.source = result.data.thumbnail_url; + refreshBuyUI(); + } + // // Function Name: fromScript() // @@ -1080,18 +1103,24 @@ Rectangle { // Description: // Called when a message is received from a script. // + function fromScript(message) { switch (message.method) { - case 'updateCheckoutQML': - root.itemId = message.params.itemId; - root.itemName = message.params.itemName.trim(); - root.itemPrice = message.params.itemPrice; - root.itemHref = message.params.itemHref; - root.referrer = message.params.referrer; - root.itemAuthor = message.params.itemAuthor; + case 'updateCheckoutQMLItemID': + if (!message.params.itemId) { + console.log("A message with method 'updateCheckoutQMLItemID' was sent without an itemId!"); + return; + } + + // If we end up following the referrer (i.e. in case the wallet "isn't set up" or the user cancels), + // we want the user to be placed back on the individual item's page - thus we set the + // default of the referrer in this case to "itemPage". + root.referrer = message.params.referrer || "itemPage"; root.itemEdition = message.params.itemEdition || -1; - root.itemType = message.params.itemType || "unknown"; - refreshBuyUI(); + root.itemId = message.params.itemId; + break; + case 'http.response': + http.handleHttpResponse(message); break; default: console.log('Checkout.qml: Unrecognized message from marketplaces.js'); diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index 2a5211d174..a719ae6432 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -56,7 +56,7 @@ Item { // Background Rectangle { z: 1; - visible: root.assetName !== "" && sendAssetStep.visible; + visible: root.assetCertID !== "" && sendAssetStep.referrer !== "payIn" && sendAssetStep.visible; anchors.top: parent.top; anchors.topMargin: root.parentAppTitleBarHeight; anchors.left: parent.left; @@ -84,7 +84,6 @@ Item { if (sendPubliclyCheckbox.checked && sendAssetStep.referrer === "nearby") { sendSignalToParent({ method: 'sendAsset_sendPublicly', - assetName: root.assetName, recipient: sendAssetStep.selectedRecipientNodeID, amount: parseInt(amountTextField.text), effectImage: root.sendingPubliclyEffectImage @@ -155,7 +154,7 @@ Item { Item { id: userInfoContainer; - visible: root.assetName === ""; + visible: root.assetCertID === ""; anchors.top: parent.top; anchors.left: parent.left; anchors.right: parent.right; @@ -251,7 +250,7 @@ Item { LinearGradient { anchors.fill: parent; - visible: root.assetName === ""; + visible: root.assetCertID === ""; start: Qt.point(0, 0); end: Qt.point(0, height); gradient: Gradient { @@ -262,7 +261,7 @@ Item { RalewaySemiBold { id: sendAssetText; - text: root.assetName === "" ? "Send Money To:" : "Gift \"" + root.assetName + "\" To:"; + text: root.assetCertID === "" ? "Send Money To:" : "Gift \"" + root.assetName + "\" To:"; // Anchors anchors.top: parent.top; anchors.topMargin: 26; @@ -441,7 +440,7 @@ Item { HiFiGlyphs { id: closeGlyphButton_connections; text: hifi.glyphs.close; - color: root.assetName === "" ? hifi.colors.lightGrayText : hifi.colors.baseGray; + color: root.assetCertID === "" ? hifi.colors.lightGrayText : hifi.colors.baseGray; size: 26; anchors.top: parent.top; anchors.topMargin: 10; @@ -684,7 +683,7 @@ Item { HiFiGlyphs { id: closeGlyphButton_nearby; text: hifi.glyphs.close; - color: root.assetName === "" ? hifi.colors.lightGrayText : hifi.colors.baseGray; + color: root.assetCertID === "" ? hifi.colors.lightGrayText : hifi.colors.baseGray; size: 26; anchors.top: parent.top; anchors.topMargin: 10; @@ -760,7 +759,7 @@ Item { RalewaySemiBold { id: sendToText; - text: root.assetName === "" ? "Send to:" : "Gift to:"; + text: root.assetCertID === "" ? "Send to:" : "Gift to:"; // Anchors anchors.top: parent.top; anchors.topMargin: 36; @@ -865,7 +864,8 @@ Item { RalewaySemiBold { id: sendAssetText_sendAssetStep; - text: root.assetName === "" ? "Send Money" : "Gift \"" + root.assetName + "\""; + text: sendAssetStep.referrer === "payIn" && root.assetCertID !== "" ? "Send Item:" : + (root.assetCertID === "" ? "Send Money To:" : "Gift \"" + root.assetName + "\" To:"); // Anchors anchors.top: parent.top; anchors.topMargin: 26; @@ -878,7 +878,7 @@ Item { // Text size size: 22; // Style - color: root.assetName === "" ? hifi.colors.white : hifi.colors.black; + color: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colors.white : hifi.colors.black; } Item { @@ -893,7 +893,7 @@ Item { RalewaySemiBold { id: sendToText_sendAssetStep; - text: root.assetName === "" ? "Send to:" : "Gift to:"; + text: (root.assetCertID === "" || sendAssetStep.referrer === "payIn") ? "Send to:" : "Gift to:"; // Anchors anchors.top: parent.top; anchors.left: parent.left; @@ -902,7 +902,7 @@ Item { // Text size size: 18; // Style - color: root.assetName === "" ? hifi.colors.white : hifi.colors.black; + color: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colors.white : hifi.colors.black; verticalAlignment: Text.AlignVCenter; } @@ -912,7 +912,7 @@ Item { anchors.right: changeButton.left; anchors.rightMargin: 12; height: parent.height; - textColor: root.assetName === "" ? hifi.colors.white : hifi.colors.black; + textColor: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colors.white : hifi.colors.black; displayName: sendAssetStep.selectedRecipientDisplayName; userName: sendAssetStep.selectedRecipientUserName; @@ -924,7 +924,7 @@ Item { // "CHANGE" button HifiControlsUit.Button { id: changeButton; - color: root.assetName === "" ? hifi.buttons.none : hifi.buttons.white; + color: root.assetCertID === "" ? hifi.buttons.none : hifi.buttons.white; colorScheme: hifi.colorSchemes.dark; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter; @@ -945,7 +945,7 @@ Item { Item { id: amountContainer; - visible: root.assetName === ""; + visible: root.assetCertID === ""; anchors.top: sendToContainer.bottom; anchors.topMargin: 2; anchors.left: parent.left; @@ -972,8 +972,8 @@ Item { HifiControlsUit.TextField { id: amountTextField; readOnly: sendAssetStep.referrer === "payIn"; - text: root.assetName === "" ? "" : "1"; - colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; + text: root.assetCertID === "" ? "" : "1"; + colorScheme: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; inputMethodHints: Qt.ImhDigitsOnly; // Anchors anchors.verticalCenter: parent.verticalCenter; @@ -1084,12 +1084,13 @@ Item { // Style background: Rectangle { anchors.fill: parent; - color: root.assetName === "" ? (optionalMessage.activeFocus && !optionalMessage.readOnly ? hifi.colors.black : hifi.colors.baseGrayShadow) : - (optionalMessage.activeFocus && !optionalMessage.readOnly ? "#EFEFEF" : "#EEEEEE"); + color: (root.assetCertID === "" || sendAssetStep.referrer === "payIn") ? + (optionalMessage.activeFocus && !optionalMessage.readOnly ? hifi.colors.black : hifi.colors.baseGrayShadow) : + (optionalMessage.activeFocus ? "#EFEFEF" : "#EEEEEE"); border.width: optionalMessage.activeFocus && !optionalMessage.readOnly ? 1 : 0; border.color: optionalMessage.activeFocus && !optionalMessage.readOnly ? hifi.colors.primaryHighlight : hifi.colors.textFieldLightBackground; } - color: root.assetName === "" ? hifi.colors.white : hifi.colors.black; + color: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colors.white : hifi.colors.black; textFormat: TextEdit.PlainText; wrapMode: TextEdit.Wrap; activeFocusOnPress: true; @@ -1125,7 +1126,8 @@ Item { // Text size size: 16; // Style - color: optionalMessage.text.length === optionalMessage.maximumLength ? "#ea89a5" : (root.assetName === "" ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight); + color: optionalMessage.text.length === optionalMessage.maximumLength ? "#ea89a5" : + (root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight); verticalAlignment: Text.AlignTop; horizontalAlignment: Text.AlignRight; } @@ -1170,7 +1172,7 @@ Item { parent.color = hifi.colors.blueAccent; } onClicked: { - lightboxPopup.titleText = (root.assetName === "" ? "Send Effect" : "Gift Effect"); + lightboxPopup.titleText = (root.assetCertID === "" ? "Send Effect" : "Gift Effect"); lightboxPopup.bodyImageSource = "sendAsset/images/send-money-effect-sm.jpg"; // Path relative to CommerceLightbox.qml lightboxPopup.bodyText = "Enabling this option will create a particle effect between you and " + "your recipient that is visible to everyone nearby."; @@ -1199,7 +1201,7 @@ Item { // "CANCEL" button HifiControlsUit.Button { id: cancelButton_sendAssetStep; - color: root.assetName === "" ? hifi.buttons.noneBorderlessWhite : hifi.buttons.noneBorderlessGray; + color: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.buttons.noneBorderlessWhite : hifi.buttons.noneBorderlessGray; colorScheme: hifi.colorSchemes.dark; anchors.right: sendButton.left; anchors.rightMargin: 24; @@ -1221,7 +1223,7 @@ Item { HifiControlsUit.Button { id: sendButton; color: hifi.buttons.blue; - colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; + colorScheme: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; anchors.right: parent.right; anchors.rightMargin: 0; anchors.verticalCenter: parent.verticalCenter; @@ -1229,11 +1231,11 @@ Item { width: 100; text: "SUBMIT"; onClicked: { - if (root.assetName === "" && parseInt(amountTextField.text) > parseInt(balanceText.text)) { + if (root.assetCertID === "" && parseInt(amountTextField.text) > parseInt(balanceText.text)) { amountTextField.focus = true; amountTextField.error = true; amountTextFieldError.text = "amount exceeds available funds"; - } else if (root.assetName === "" && (amountTextField.text === "" || parseInt(amountTextField.text) < 1)) { + } else if (root.assetCertID === "" && (amountTextField.text === "" || parseInt(amountTextField.text) < 1)) { amountTextField.focus = true; amountTextField.error = true; amountTextFieldError.text = "invalid amount"; @@ -1324,18 +1326,18 @@ Item { Rectangle { anchors.top: parent.top; - anchors.topMargin: root.assetName === "" ? 15 : 125; + anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 125; anchors.left: parent.left; - anchors.leftMargin: root.assetName === "" ? 15 : 50; + anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; anchors.right: parent.right; - anchors.rightMargin: root.assetName === "" ? 15 : 50; + anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetName === "" ? 15 : 125; + anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 125; color: "#FFFFFF"; RalewaySemiBold { id: paymentSentText; - text: root.assetName === "" ? "Payment Sent" : "Gift Sent"; + text: root.assetCertID === "" ? "Payment Sent" : (sendAssetStep.referrer === "payIn" ? "Item Sent" : "Gift Sent"); // Anchors anchors.top: parent.top; anchors.topMargin: 26; @@ -1353,7 +1355,7 @@ Item { HiFiGlyphs { id: closeGlyphButton_paymentSuccess; - visible: root.assetName === ""; + visible: root.assetCertID === "" && sendAssetStep.referrer !== "payIn"; text: hifi.glyphs.close; color: hifi.colors.lightGrayText; size: 26; @@ -1427,7 +1429,7 @@ Item { Item { id: giftContainer_paymentSuccess; - visible: root.assetName !== ""; + visible: root.assetCertID !== "" && sendAssetStep.referrer !== "payIn"; anchors.top: sendToContainer_paymentSuccess.bottom; anchors.topMargin: 8; anchors.left: parent.left; @@ -1469,7 +1471,7 @@ Item { Item { id: amountContainer_paymentSuccess; - visible: root.assetName === ""; + visible: root.assetCertID === ""; anchors.top: sendToContainer_paymentSuccess.bottom; anchors.topMargin: 16; anchors.left: parent.left; @@ -1524,7 +1526,7 @@ Item { RalewaySemiBold { id: optionalMessage_paymentSuccess; - visible: root.assetName === ""; + visible: root.assetCertID === "" || sendAssetStep.referrer === "payIn"; text: optionalMessage.text; // Anchors anchors.top: amountContainer_paymentSuccess.visible ? amountContainer_paymentSuccess.bottom : sendToContainer_paymentSuccess.bottom; @@ -1546,18 +1548,22 @@ Item { HifiControlsUit.Button { id: closeButton; color: hifi.buttons.blue; - colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; + colorScheme: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; anchors.horizontalCenter: parent.horizontalCenter; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetName === "" ? 80 : 30; + anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 80 : 30; height: 50; width: 120; text: "Close"; onClicked: { - root.nextActiveView = "sendAssetHome"; - resetSendAssetData(); - if (root.assetName !== "") { - sendSignalToParent({method: "closeSendAsset"}); + if (sendAssetStep.referrer === "payIn") { + sendToScript({method: "closeSendAsset"}); + } else { + root.nextActiveView = "sendAssetHome"; + resetSendAssetData(); + if (root.assetName !== "") { + sendSignalToParent({method: "closeSendAsset"}); + } } } } @@ -1585,18 +1591,18 @@ Item { Rectangle { anchors.top: parent.top; - anchors.topMargin: root.assetName === "" ? 15 : 150; + anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 150; anchors.left: parent.left; - anchors.leftMargin: root.assetName === "" ? 15 : 50; + anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; anchors.right: parent.right; - anchors.rightMargin: root.assetName === "" ? 15 : 50; + anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetName === "" ? 15 : 300; + anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 300; color: "#FFFFFF"; RalewaySemiBold { id: paymentFailureText; - text: root.assetName === "" ? "Payment Failed" : "Failed"; + text: root.assetCertID === "" && sendAssetStep.referrer !== "payIn" ? "Payment Failed" : "Failed"; // Anchors anchors.top: parent.top; anchors.topMargin: 26; @@ -1614,7 +1620,7 @@ Item { HiFiGlyphs { id: closeGlyphButton_paymentFailure; - visible: root.assetName === ""; + visible: root.assetCertID === "" && sendAssetStep.referrer !== "payIn"; text: hifi.glyphs.close; color: hifi.colors.lightGrayText; size: 26; @@ -1643,7 +1649,8 @@ Item { RalewaySemiBold { id: paymentFailureDetailText; - text: "The recipient you specified was unable to receive your " + (root.assetName === "" ? "payment." : "gift."); + text: "The recipient you specified was unable to receive your " + + (root.assetCertID === "" ? "payment." : (sendAssetStep.referrer === "payIn" ? "item." : "gift.")); anchors.top: paymentFailureText.bottom; anchors.topMargin: 20; anchors.left: parent.left; @@ -1661,7 +1668,7 @@ Item { Item { id: sendToContainer_paymentFailure; - visible: root.assetName === ""; + visible: root.assetCertID === "" || sendAssetStep.referrer === "payIn"; anchors.top: paymentFailureDetailText.bottom; anchors.topMargin: 8; anchors.left: parent.left; @@ -1702,7 +1709,7 @@ Item { Item { id: amountContainer_paymentFailure; - visible: root.assetName === ""; + visible: root.assetCertID === ""; anchors.top: sendToContainer_paymentFailure.bottom; anchors.topMargin: 16; anchors.left: parent.left; @@ -1757,7 +1764,7 @@ Item { RalewaySemiBold { id: optionalMessage_paymentFailure; - visible: root.assetName === ""; + visible: root.assetCertID === "" || sendAssetStep.referrer === "payIn"; text: optionalMessage.text; // Anchors anchors.top: amountContainer_paymentFailure.visible ? amountContainer_paymentFailure.bottom : sendToContainer_paymentFailure.bottom; @@ -1779,19 +1786,23 @@ Item { HifiControlsUit.Button { id: closeButton_paymentFailure; color: hifi.buttons.noneBorderless; - colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; + colorScheme: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; anchors.right: retryButton_paymentFailure.left; anchors.rightMargin: 12; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetName === "" ? 80 : 30; + anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 80 : 30; height: 50; width: 120; text: "Cancel"; onClicked: { - root.nextActiveView = "sendAssetHome"; - resetSendAssetData(); - if (root.assetName !== "") { - sendSignalToParent({method: "closeSendAsset"}); + if (sendAssetStep.referrer === "payIn") { + sendToScript({method: "closeSendAsset"}); + } else { + root.nextActiveView = "sendAssetHome"; + resetSendAssetData(); + if (root.assetName !== "") { + sendSignalToParent({method: "closeSendAsset"}); + } } } } @@ -1800,17 +1811,17 @@ Item { HifiControlsUit.Button { id: retryButton_paymentFailure; color: hifi.buttons.blue; - colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; + colorScheme: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; anchors.right: parent.right; anchors.rightMargin: 12; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetName === "" ? 80 : 30; + anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 80 : 30; height: 50; width: 120; text: "Retry"; onClicked: { root.isCurrentlySendingAsset = true; - if (sendAssetStep.referrer === "connections") { + if (sendAssetStep.referrer === "connections" || sendAssetStep.referrer === "payIn") { Commerce.transferAssetToUsername(sendAssetStep.selectedRecipientUserName, root.assetCertID, parseInt(amountTextField.text), @@ -1878,9 +1889,13 @@ Item { sendAssetStep.selectedRecipientUserName = message.userName; break; case 'updateSendAssetQML': - root.assetName = message.assetName || ""; + root.assetName = ""; root.assetCertID = message.assetCertID || ""; - amountTextField.text = message.amount || 1; + if (root.assetCertID === "") { + amountTextField.text = message.amount || 1; + } else { + amountTextField.text = ""; + } sendAssetStep.referrer = "payIn"; sendAssetStep.selectedRecipientNodeID = ""; sendAssetStep.selectedRecipientDisplayName = 'Secure Payment'; diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js index 1bfa9d4b20..e3da1c2577 100644 --- a/scripts/system/html/js/marketplacesInject.js +++ b/scripts/system/html/js/marketplacesInject.js @@ -219,17 +219,12 @@ }); } - function buyButtonClicked(id, name, author, price, href, referrer, edition, type) { + function buyButtonClicked(id, referrer, edition) { EventBridge.emitWebEvent(JSON.stringify({ type: "CHECKOUT", itemId: id, - itemName: name, - itemPrice: price ? parseInt(price, 10) : 0, - itemHref: href, referrer: referrer, - itemAuthor: author, - itemEdition: edition, - itemType: type.trim() + itemEdition: edition })); } @@ -313,13 +308,8 @@ return false; } buyButtonClicked($(this).closest('.grid-item').attr('data-item-id'), - $(this).closest('.grid-item').find('.item-title').text(), - $(this).closest('.grid-item').find('.creator').find('.value').text(), - $(this).closest('.grid-item').find('.item-cost').text(), - $(this).attr('data-href'), "mainPage", - -1, - $(this).closest('.grid-item').find('.item-type').text()); + -1); }); } @@ -427,13 +417,8 @@ purchaseButton.on('click', function () { if ('available' === availability || isUpdating) { buyButtonClicked(window.location.pathname.split("/")[3], - $('#top-center').find('h1').text(), - $('#creator').find('.value').text(), - cost, - href, "itemPage", - urlParams.get('edition'), - type); + urlParams.get('edition')); } }); } diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index be25d1265f..e4891a9bae 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -471,7 +471,7 @@ function onWebEventReceived(message) { wireQmlEventBridge(true); ui.open(MARKETPLACE_CHECKOUT_QML_PATH); ui.tablet.sendToQml({ - method: 'updateCheckoutQML', + method: 'updateCheckoutQMLItemID', params: message }); } else if (message.type === "REQUEST_SETTING") { @@ -649,8 +649,8 @@ var onQmlMessageReceived = function onQmlMessageReceived(message) { case 'purchases_openGoTo': case 'purchases_itemInfoClicked': case 'purchases_itemCertificateClicked': - case 'clearShouldShowDotHistory': - case 'giftAsset': + case 'clearShouldShowDotHistory': + case 'giftAsset': break; default: print('marketplaces.js: Unrecognized message from Checkout.qml'); From a9fd443f28ce203ccb0093275166d4653c7eb8bc Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 26 Nov 2018 16:03:07 -0800 Subject: [PATCH 09/13] 'improve' UI slightly --- .../hifi/commerce/common/sendAsset/RecipientDisplay.qml | 7 ++++--- .../qml/hifi/commerce/common/sendAsset/SendAsset.qml | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/RecipientDisplay.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/RecipientDisplay.qml index 9e1a967d50..10756957d3 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/RecipientDisplay.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/RecipientDisplay.qml @@ -25,14 +25,15 @@ Item { id: root; - property bool isDisplayingNearby; // as opposed to 'connections' + // true when sending to 'nearby' or when a script raises the send asset dialog + property bool multiLineDisplay; property string displayName; property string userName; property string profilePic; property string textColor: hifi.colors.white; Item { - visible: root.isDisplayingNearby; + visible: root.multiLineDisplay; anchors.fill: parent; RalewaySemiBold { @@ -71,7 +72,7 @@ Item { } Item { - visible: !root.isDisplayingNearby; + visible: !root.multiLineDisplay; anchors.fill: parent; Image { diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index a719ae6432..ebb2a7f59c 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -918,7 +918,7 @@ Item { userName: sendAssetStep.selectedRecipientUserName; profilePic: sendAssetStep.selectedRecipientProfilePic !== "" ? ((0 === sendAssetStep.selectedRecipientProfilePic.indexOf("http")) ? sendAssetStep.selectedRecipientProfilePic : (Account.metaverseServerURL + sendAssetStep.selectedRecipientProfilePic)) : ""; - isDisplayingNearby: sendAssetStep.referrer === "nearby"; + multiLineDisplay: sendAssetStep.referrer === "nearby" || sendAssetStep.referrer === "payIn"; } // "CHANGE" button @@ -1422,7 +1422,7 @@ Item { userName: sendAssetStep.selectedRecipientUserName; profilePic: sendAssetStep.selectedRecipientProfilePic !== "" ? ((0 === sendAssetStep.selectedRecipientProfilePic.indexOf("http")) ? sendAssetStep.selectedRecipientProfilePic : (Account.metaverseServerURL + sendAssetStep.selectedRecipientProfilePic)) : ""; - isDisplayingNearby: sendAssetStep.referrer === "nearby"; + multiLineDisplay: sendAssetStep.referrer === "nearby" || sendAssetStep.referrer === "payIn"; } } @@ -1703,7 +1703,7 @@ Item { userName: sendAssetStep.selectedRecipientUserName; profilePic: sendAssetStep.selectedRecipientProfilePic !== "" ? ((0 === sendAssetStep.selectedRecipientProfilePic.indexOf("http")) ? sendAssetStep.selectedRecipientProfilePic : (Account.metaverseServerURL + sendAssetStep.selectedRecipientProfilePic)) : ""; - isDisplayingNearby: sendAssetStep.referrer === "nearby"; + multiLineDisplay: sendAssetStep.referrer === "nearby" || sendAssetStep.referrer === "payIn"; } } @@ -1898,7 +1898,7 @@ Item { } sendAssetStep.referrer = "payIn"; sendAssetStep.selectedRecipientNodeID = ""; - sendAssetStep.selectedRecipientDisplayName = 'Secure Payment'; + sendAssetStep.selectedRecipientDisplayName = "Determined by script:"; sendAssetStep.selectedRecipientUserName = message.username; optionalMessage.text = message.message || "No Message Provided"; From c4a9ca3445e3d499ae87e6417bc02b81722f9512 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 27 Nov 2018 09:32:37 -0800 Subject: [PATCH 10/13] fix interface crashing when reloading scripts --- libraries/script-engine/src/ScriptEngines.cpp | 39 ++++++++----------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 2cdfc20647..399ccf1919 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -191,7 +191,6 @@ void ScriptEngines::shutdownScripting() { // Gracefully stop the engine's scripting thread scriptEngine->stop(); - removeScriptEngine(scriptEngine); // We need to wait for the engine to be done running before we proceed, because we don't // want any of the scripts final "scriptEnding()" or pending "update()" methods from accessing @@ -370,13 +369,10 @@ QStringList ScriptEngines::getRunningScripts() { } void ScriptEngines::stopAllScripts(bool restart) { - QVector toReload; QReadLocker lock(&_scriptEnginesHashLock); if (_isReloading) { return; - } else { - _isReloading = true; } for (QHash::const_iterator it = _scriptEnginesHash.constBegin(); @@ -389,29 +385,27 @@ void ScriptEngines::stopAllScripts(bool restart) { // queue user scripts if restarting if (restart && scriptEngine->isUserLoaded()) { - toReload << it.key().toString(); + _isReloading = true; + bool lastScript = (it == _scriptEnginesHash.constEnd() - 1); + ScriptEngine::Type type = scriptEngine->getType(); + + connect(scriptEngine.data(), &ScriptEngine::finished, this, [this, type, lastScript] (QString scriptName) { + reloadScript(scriptName, true)->setType(type); + + if (lastScript) { + _isReloading = false; + } + }); } // stop all scripts scriptEngine->stop(); - removeScriptEngine(scriptEngine); } - // wait for engines to stop (ie: providing time for .scriptEnding cleanup handlers to run) before - // triggering reload of any Client scripts / Entity scripts - QTimer::singleShot(1000, this, [=]() { - for(const auto &scriptName : toReload) { - auto scriptEngine = getScriptEngine(scriptName); - if (scriptEngine && !scriptEngine->isFinished()) { - scriptEngine->waitTillDoneRunning(); - } - reloadScript(scriptName); - } - if (restart) { - qCDebug(scriptengine) << "stopAllScripts -- emitting scriptsReloading"; - emit scriptsReloading(); - } - _isReloading = false; - }); + + if (restart) { + qCDebug(scriptengine) << "stopAllScripts -- emitting scriptsReloading"; + emit scriptsReloading(); + } } bool ScriptEngines::stopScript(const QString& rawScriptURL, bool restart) { @@ -439,7 +433,6 @@ bool ScriptEngines::stopScript(const QString& rawScriptURL, bool restart) { } } scriptEngine->stop(); - removeScriptEngine(scriptEngine); stoppedScript = true; } } From 67dfccafec2a426efbe2aecc9cec0ce50eb11361 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 27 Nov 2018 10:19:14 -0800 Subject: [PATCH 11/13] Show item name when sending item --- .../commerce/common/sendAsset/SendAsset.qml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index ebb2a7f59c..2d0bb2d87b 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -107,6 +107,14 @@ Item { root.nextActiveView = 'paymentFailure'; } } + + onCertificateInfoResult: { + if (result.status !== 'success') { + console.log("Failed to get certificate info", result.data.message); + } else { + root.assetName = result.data.marketplace_item_name; + } + } } Connections { @@ -864,7 +872,7 @@ Item { RalewaySemiBold { id: sendAssetText_sendAssetStep; - text: sendAssetStep.referrer === "payIn" && root.assetCertID !== "" ? "Send Item:" : + text: sendAssetStep.referrer === "payIn" && root.assetCertID !== "" ? "Send \"" + root.assetName + "\":" : (root.assetCertID === "" ? "Send Money To:" : "Gift \"" + root.assetName + "\" To:"); // Anchors anchors.top: parent.top; @@ -1429,7 +1437,7 @@ Item { Item { id: giftContainer_paymentSuccess; - visible: root.assetCertID !== "" && sendAssetStep.referrer !== "payIn"; + visible: root.assetCertID !== ""; anchors.top: sendToContainer_paymentSuccess.bottom; anchors.topMargin: 8; anchors.left: parent.left; @@ -1440,7 +1448,7 @@ Item { RalewaySemiBold { id: gift_paymentSuccess; - text: "Gift:"; + text: sendAssetStep.referrer === "payIn" ? "Item:" : "Gift:"; // Anchors anchors.top: parent.top; anchors.left: parent.left; @@ -1526,7 +1534,7 @@ Item { RalewaySemiBold { id: optionalMessage_paymentSuccess; - visible: root.assetCertID === "" || sendAssetStep.referrer === "payIn"; + visible: root.assetCertID === ""; text: optionalMessage.text; // Anchors anchors.top: amountContainer_paymentSuccess.visible ? amountContainer_paymentSuccess.bottom : sendToContainer_paymentSuccess.bottom; @@ -1895,6 +1903,7 @@ Item { amountTextField.text = message.amount || 1; } else { amountTextField.text = ""; + Commerce.certificateInfo(root.assetCertID); } sendAssetStep.referrer = "payIn"; sendAssetStep.selectedRecipientNodeID = ""; From 8f21ade0c707d3f3eb76eb57da7c694cb62d618c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 23 Nov 2018 19:56:35 -0800 Subject: [PATCH 12/13] make cmake -DDISABLE_QML=1 work again --- interface/src/Application.cpp | 145 +++++++++++++----- interface/src/Application_render.cpp | 2 + interface/src/ConnectionMonitor.cpp | 4 + interface/src/ui/ApplicationOverlay.cpp | 2 + interface/src/ui/OverlayConductor.cpp | 2 + interface/src/ui/OverlayConductor.h | 2 + interface/src/ui/overlays/Overlays.cpp | 4 + libraries/shared/src/DependencyManager.h | 30 ++-- libraries/ui/src/OffscreenUi.cpp | 4 +- libraries/ui/src/ui/Menu.cpp | 64 +++++--- .../ui/src/ui/TabletScriptingInterface.cpp | 2 + 11 files changed, 185 insertions(+), 76 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fb6e8ec566..21af28ffcb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -927,7 +927,9 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { #endif DependencyManager::set(); DependencyManager::set(); +#if !defined(DISABLE_QML) DependencyManager::set(); +#endif DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); @@ -1000,6 +1002,14 @@ const bool DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS = false; const QString DEFAULT_CURSOR_NAME = "DEFAULT"; const bool DEFAULT_MINI_TABLET_ENABLED = true; +QSharedPointer getOffscreenUI() { +#if !defined(DISABLE_QML) + return DependencyManager::get(); +#else + return nullptr; +#endif +} + Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bool runningMarkerExisted) : QApplication(argc, argv), _window(new MainWindow(desktop())), @@ -1604,7 +1614,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto userInputMapper = DependencyManager::get(); connect(userInputMapper.data(), &UserInputMapper::actionEvent, [this](int action, float state) { using namespace controller; - auto offscreenUi = DependencyManager::get(); auto tabletScriptingInterface = DependencyManager::get(); { auto actionEnum = static_cast(action); @@ -1743,7 +1752,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return qApp->getMyAvatar()->getCharacterController()->onGround() ? 1 : 0; }); _applicationStateDevice->setInputVariant(STATE_NAV_FOCUSED, []() -> float { - return DependencyManager::get()->navigationFocused() ? 1 : 0; + auto offscreenUi = getOffscreenUI(); + return offscreenUi ? (offscreenUi->navigationFocused() ? 1 : 0) : 0; }); _applicationStateDevice->setInputVariant(STATE_PLATFORM_WINDOWS, []() -> float { #if defined(Q_OS_WIN) @@ -1809,9 +1819,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Now that we've loaded the menu and thus switched to the previous display plugin // we can unlock the desktop repositioning code, since all the positions will be // relative to the desktop size for this plugin - auto offscreenUi = DependencyManager::get(); + auto offscreenUi = getOffscreenUI(); connect(offscreenUi.data(), &OffscreenUi::desktopReady, []() { - auto offscreenUi = DependencyManager::get(); + auto offscreenUi = getOffscreenUI(); auto desktop = offscreenUi->getDesktop(); if (desktop) { desktop->setProperty("repositionLocked", false); @@ -2372,6 +2382,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(&AndroidHelper::instance(), &AndroidHelper::enterForeground, this, &Application::enterForeground); AndroidHelper::instance().notifyLoadComplete(); #else +#if !defined(DISABLE_QML) // Do not show login dialog if requested not to on the command line const QString HIFI_NO_LOGIN_COMMAND_LINE_KEY = "--no-login-suggestion"; int index = arguments().indexOf(HIFI_NO_LOGIN_COMMAND_LINE_KEY); @@ -2396,6 +2407,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo checkLoginTimer->start(); } #endif +#endif } void Application::updateVerboseLogging() { @@ -2546,7 +2558,9 @@ void Application::onAboutToQuit() { DependencyManager::get()->startThread(); // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. - DependencyManager::get()->hide("RunningScripts"); +#if !defined(DISABLE_QML) + getOffscreenUI()->hide("RunningScripts"); +#endif _aboutToQuit = true; @@ -2784,10 +2798,10 @@ void Application::initializeGL() { _glWidget->windowHandle()->setFormat(getDefaultOpenGLSurfaceFormat()); // When loading QtWebEngineWidgets, it creates a global share context on startup. - // We have to account for this possibility by checking here for an existing + // We have to account for this possibility by checking here for an existing // global share context auto globalShareContext = qt_gl_global_share_context(); - + #if !defined(DISABLE_QML) // Build a shared canvas / context for the Chromium processes if (!globalShareContext) { @@ -2974,7 +2988,9 @@ void Application::initializeRenderEngine() { } extern void setupPreferences(); +#if !defined(DISABLE_QML) static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, int index, bool active = false); +#endif void Application::initializeUi() { AddressBarDialog::registerType(); @@ -3024,12 +3040,13 @@ void Application::initializeUi() { tabletScriptingInterface->getTablet(SYSTEM_TABLET); } - auto offscreenUi = DependencyManager::get(); + auto offscreenUi = getOffscreenUI(); connect(offscreenUi.data(), &hifi::qml::OffscreenSurface::rootContextCreated, this, &Application::onDesktopRootContextCreated); connect(offscreenUi.data(), &hifi::qml::OffscreenSurface::rootItemCreated, this, &Application::onDesktopRootItemCreated); +#if !defined(DISABLE_QML) offscreenUi->setProxyWindow(_window->windowHandle()); // OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to // support the window management and scripting proxies for VR use @@ -3039,9 +3056,13 @@ void Application::initializeUi() { // FIXME either expose so that dialogs can set this themselves or // do better detection in the offscreen UI of what has focus offscreenUi->setNavigationFocused(false); +#else + _window->setMenuBar(new Menu()); +#endif setupPreferences(); +#if !defined(DISABLE_QML) _glWidget->installEventFilter(offscreenUi.data()); offscreenUi->setMouseTranslator([=](const QPointF& pt) { QPointF result = pt; @@ -3054,6 +3075,7 @@ void Application::initializeUi() { return result.toPoint(); }); offscreenUi->resume(); +#endif connect(_window, &MainWindow::windowGeometryChanged, [this](const QRect& r){ resizeGL(); if (_touchscreenVirtualPadDevice) { @@ -3092,6 +3114,7 @@ void Application::initializeUi() { } }); +#if !defined(DISABLE_QML) // Pre-create a couple of Web3D overlays to speed up tablet UI auto offscreenSurfaceCache = DependencyManager::get(); offscreenSurfaceCache->setOnRootContextCreated([&](const QString& rootObject, QQmlContext* surfaceContext) { @@ -3105,9 +3128,11 @@ void Application::initializeUi() { offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1); offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2); +#endif flushMenuUpdates(); +#if !defined(DISABLE_QML) // Now that the menu is instantiated, ensure the display plugin menu is properly updated { auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); @@ -3126,6 +3151,7 @@ void Application::initializeUi() { auto parent = getPrimaryMenu()->getMenu(MenuOption::OutputMenu); parent->addSeparator(); } +#endif // The display plugins are created before the menu now, so we need to do this here to hide the menu bar // now that it exists @@ -3230,12 +3256,12 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { void Application::onDesktopRootItemCreated(QQuickItem* rootItem) { Stats::show(); AnimStats::show(); - auto surfaceContext = DependencyManager::get()->getSurfaceContext(); + auto surfaceContext = getOffscreenUI()->getSurfaceContext(); surfaceContext->setContextProperty("Stats", Stats::getInstance()); surfaceContext->setContextProperty("AnimStats", AnimStats::getInstance()); #if !defined(Q_OS_ANDROID) - auto offscreenUi = DependencyManager::get(); + auto offscreenUi = getOffscreenUI(); auto qml = PathUtils::qmlUrl("AvatarInputsBar.qml"); offscreenUi->show(qml, "AvatarInputsBar"); #endif @@ -3418,7 +3444,7 @@ void Application::setPreferredCursor(const QString& cursorName) { void Application::setSettingConstrainToolbarPosition(bool setting) { _constrainToolbarPosition.set(setting); - DependencyManager::get()->setConstrainToolbarToCenterX(setting); + getOffscreenUI()->setConstrainToolbarToCenterX(setting); } void Application::setMiniTabletEnabled(bool enabled) { @@ -3512,7 +3538,9 @@ void Application::resizeGL() { _myCamera.loadViewFrustum(_viewFrustum); } - DependencyManager::get()->resize(fromGlm(displayPlugin->getRecommendedUiSize())); +#if !defined(DISABLE_QML) + getOffscreenUI()->resize(fromGlm(displayPlugin->getRecommendedUiSize())); +#endif } void Application::handleSandboxStatus(QNetworkReply* reply) { @@ -3912,10 +3940,12 @@ bool Application::eventFilter(QObject* object, QEvent* event) { } if (event->type() == QEvent::ShortcutOverride) { - if (DependencyManager::get()->shouldSwallowShortcut(event)) { +#if !defined(DISABLE_QML) + if (getOffscreenUI()->shouldSwallowShortcut(event)) { event->accept(); return true; } +#endif // Filter out captured keys before they're used for shortcut actions. if (_controllerScriptingInterface->isKeyCaptured(static_cast(event))) { @@ -3998,7 +4028,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_X: if (isShifted && isMeta) { - auto offscreenUi = DependencyManager::get(); + auto offscreenUi = getOffscreenUI(); offscreenUi->togglePinned(); //offscreenUi->getSurfaceContext()->engine()->clearComponentCache(); //OffscreenUi::information("Debugging", "Component cache cleared"); @@ -4014,7 +4044,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_B: if (isMeta) { - auto offscreenUi = DependencyManager::get(); + auto offscreenUi = getOffscreenUI(); offscreenUi->load("Browser.qml"); } else if (isOption) { controller::InputRecorder* inputRecorder = controller::InputRecorder::getInstance(); @@ -4036,7 +4066,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_R: if (isMeta && !event->isAutoRepeat()) { DependencyManager::get()->reloadAllScripts(); - DependencyManager::get()->clearCache(); + getOffscreenUI()->clearCache(); } break; @@ -4233,9 +4263,13 @@ void Application::mouseMoveEvent(QMouseEvent* event) { return; // bail } - auto offscreenUi = DependencyManager::get(); +#if !defined(DISABLE_QML) + auto offscreenUi = getOffscreenUI(); auto eventPosition = compositor.getMouseEventPosition(event); - QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition); + QPointF transformedPos = offscreenUi ? offscreenUi->mapToVirtualScreen(eventPosition) : QPointF(); +#else + QPointF transformedPos; +#endif auto button = event->button(); auto buttons = event->buttons(); // Determine if the ReticleClick Action is 1 and if so, fake include the LeftMouseButton @@ -4273,7 +4307,8 @@ void Application::mousePressEvent(QMouseEvent* event) { // Inhibit the menu if the user is using alt-mouse dragging _altPressed = false; - auto offscreenUi = DependencyManager::get(); +#if !defined(DISABLE_QML) + auto offscreenUi = getOffscreenUI(); // If we get a mouse press event it means it wasn't consumed by the offscreen UI, // hence, we should defocus all of the offscreen UI windows, in order to allow // keyboard shortcuts not to be swallowed by them. In particular, WebEngineViews @@ -4282,6 +4317,9 @@ void Application::mousePressEvent(QMouseEvent* event) { auto eventPosition = getApplicationCompositor().getMouseEventPosition(event); QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition); +#else + QPointF transformedPos; +#endif QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), @@ -4318,9 +4356,13 @@ void Application::mousePressEvent(QMouseEvent* event) { } void Application::mouseDoublePressEvent(QMouseEvent* event) { - auto offscreenUi = DependencyManager::get(); +#if !defined(DISABLE_QML) + auto offscreenUi = getOffscreenUI(); auto eventPosition = getApplicationCompositor().getMouseEventPosition(event); QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition); +#else + QPointF transformedPos; +#endif QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), @@ -4341,9 +4383,13 @@ void Application::mouseDoublePressEvent(QMouseEvent* event) { void Application::mouseReleaseEvent(QMouseEvent* event) { - auto offscreenUi = DependencyManager::get(); +#if !defined(DISABLE_QML) + auto offscreenUi = getOffscreenUI(); auto eventPosition = getApplicationCompositor().getMouseEventPosition(event); QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition); +#else + QPointF transformedPos; +#endif QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), @@ -4739,7 +4785,8 @@ void Application::idle() { // Update the deadlock watchdog updateHeartbeat(); - auto offscreenUi = DependencyManager::get(); +#if !defined(DISABLE_QML) + auto offscreenUi = getOffscreenUI(); // These tasks need to be done on our first idle, because we don't want the showing of // overlay subwindows to do a showDesktop() until after the first time through @@ -4748,6 +4795,7 @@ void Application::idle() { firstIdle = false; connect(offscreenUi.data(), &OffscreenUi::showDesktop, this, &Application::showDesktop); } +#endif #ifdef Q_OS_WIN // If tracing is enabled then monitor the CPU in a separate thread @@ -4764,6 +4812,7 @@ void Application::idle() { #endif auto displayPlugin = getActiveDisplayPlugin(); +#if !defined(DISABLE_QML) if (displayPlugin) { auto uiSize = displayPlugin->getRecommendedUiSize(); // Bit of a hack since there's no device pixel ratio change event I can find. @@ -4772,6 +4821,7 @@ void Application::idle() { offscreenUi->resize(fromGlm(uiSize)); } } +#endif if (displayPlugin) { PROFILE_COUNTER_IF_CHANGED(app, "present", float, displayPlugin->presentRate()); @@ -4806,6 +4856,7 @@ void Application::idle() { float secondsSinceLastUpdate = (float)_lastTimeUpdated.nsecsElapsed() / NSECS_PER_MSEC / MSECS_PER_SECOND; _lastTimeUpdated.start(); +#if !defined(DISABLE_QML) // If the offscreen Ui has something active that is NOT the root, then assume it has keyboard focus. if (offscreenUi && offscreenUi->getWindow()) { auto activeFocusItem = offscreenUi->getWindow()->activeFocusItem(); @@ -4817,9 +4868,11 @@ void Application::idle() { _keyboardDeviceHasFocus = true; } } +#endif checkChangeCursor(); +#if !defined(DISABLE_QML) auto stats = Stats::getInstance(); if (stats) { stats->updateStats(); @@ -4828,6 +4881,7 @@ void Application::idle() { if (animStats) { animStats->updateStats(); } +#endif // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing // details if we're in ExtraDebugging mode. However, the ::update() and its subcomponents will show their timing @@ -5163,7 +5217,9 @@ QVector Application::pasteEntities(float x, float y, float z) { void Application::init() { // Make sure Login state is up to date +#if !defined(DISABLE_QML) DependencyManager::get()->toggleLoginDialog(); +#endif if (!DISABLE_DEFERRED) { DependencyManager::get()->init(); } @@ -6702,8 +6758,9 @@ void Application::nodeActivated(SharedNodePointer node) { if (node->getType() == NodeType::AssetServer) { // asset server just connected - check if we have the asset browser showing - auto offscreenUi = DependencyManager::get(); - auto assetDialog = offscreenUi->getRootItem()->findChild("AssetServer"); +#if !defined(DISABLE_QML) + auto offscreenUi = getOffscreenUI(); + auto assetDialog = offscreenUi ? offscreenUi->getRootItem()->findChild("AssetServer") : nullptr; if (assetDialog) { auto nodeList = DependencyManager::get(); @@ -6716,6 +6773,7 @@ void Application::nodeActivated(SharedNodePointer node) { assetDialog->setVisible(false); } } +#endif } // If we get a new EntityServer activated, reset lastQueried time @@ -6773,13 +6831,15 @@ void Application::nodeKilled(SharedNodePointer node) { } else if (node->getType() == NodeType::AssetServer) { // asset server going away - check if we have the asset browser showing - auto offscreenUi = DependencyManager::get(); - auto assetDialog = offscreenUi->getRootItem()->findChild("AssetServer"); +#if !defined(DISABLE_QML) + auto offscreenUi = getOffscreenUI(); + auto assetDialog = offscreenUi ? offscreenUi->getRootItem()->findChild("AssetServer") : nullptr; if (assetDialog) { // call reload on the shown asset browser dialog QMetaObject::invokeMethod(assetDialog, "clear"); } +#endif } } @@ -6886,8 +6946,10 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe qScriptRegisterMetaType(scriptEngine.data(), RayToOverlayIntersectionResultToScriptValue, RayToOverlayIntersectionResultFromScriptValue); - scriptEngine->registerGlobalObject("OffscreenFlags", DependencyManager::get()->getFlags()); +#if !defined(DISABLE_QML) + scriptEngine->registerGlobalObject("OffscreenFlags", getOffscreenUI()->getFlags()); scriptEngine->registerGlobalObject("Desktop", DependencyManager::get().data()); +#endif qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue, wrapperFromScriptValue); qScriptRegisterMetaType(scriptEngine.data(), @@ -6913,14 +6975,16 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe bool clientScript = scriptEngine->isClientScript(); scriptEngine->registerFunction("OverlayWindow", clientScript ? QmlWindowClass::constructor : QmlWindowClass::restricted_constructor); -#if !defined(Q_OS_ANDROID) +#if !defined(Q_OS_ANDROID) && !defined(DISABLE_QML) scriptEngine->registerFunction("OverlayWebWindow", clientScript ? QmlWebWindowClass::constructor : QmlWebWindowClass::restricted_constructor); #endif scriptEngine->registerFunction("QmlFragment", clientScript ? QmlFragmentClass::constructor : QmlFragmentClass::restricted_constructor); scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("DesktopPreviewProvider", DependencyManager::get().data()); +#if !defined(DISABLE_QML) scriptEngine->registerGlobalObject("Stats", Stats::getInstance()); +#endif scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("Snapshot", DependencyManager::get().data()); scriptEngine->registerGlobalObject("AudioStats", DependencyManager::get()->getStats().data()); @@ -7116,7 +7180,7 @@ bool Application::askToSetAvatarUrl(const QString& url) { qCDebug(interfaceapp) << "Declined to agree to avatar license"; } - //auto offscreenUi = DependencyManager::get(); + //auto offscreenUi = getOffscreenUI(); }); } else { setAvatar(url, modelName); @@ -7314,7 +7378,9 @@ void Application::showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const toggleTabletUI(true); } } else { - DependencyManager::get()->show(widgetUrl, name); +#if !defined(DISABLE_QML) + getOffscreenUI()->show(widgetUrl, name); +#endif } } @@ -7339,10 +7405,10 @@ void Application::showAssetServerWidget(QString filePath) { auto tablet = dynamic_cast(tabletScriptingInterface->getTablet(SYSTEM_TABLET)); auto hmd = DependencyManager::get(); if (tablet->getToolbarMode()) { - DependencyManager::get()->show(url, "AssetServer", startUpload); + getOffscreenUI()->show(url, "AssetServer", startUpload); } else { if (!hmd->getShouldShowTablet() && !isHMDMode()) { - DependencyManager::get()->show(url, "AssetServer", startUpload); + getOffscreenUI()->show(url, "AssetServer", startUpload); } else { static const QUrl url("hifi/dialogs/TabletAssetServer.qml"); if (!tablet->isPathLoaded(url)) { @@ -7697,7 +7763,7 @@ void Application::addAssetToWorldInfo(QString modelName, QString infoText) { if (!_addAssetToWorldErrorTimer.isActive()) { if (!_addAssetToWorldMessageBox) { - _addAssetToWorldMessageBox = DependencyManager::get()->createMessageBox(OffscreenUi::ICON_INFORMATION, + _addAssetToWorldMessageBox = getOffscreenUI()->createMessageBox(OffscreenUi::ICON_INFORMATION, "Downloading Model", "", QMessageBox::NoButton, QMessageBox::NoButton); connect(_addAssetToWorldMessageBox, SIGNAL(destroyed()), this, SLOT(onAssetToWorldMessageBoxClosed())); } @@ -7780,7 +7846,7 @@ void Application::addAssetToWorldError(QString modelName, QString errorText) { addAssetToWorldInfoClear(modelName); if (!_addAssetToWorldMessageBox) { - _addAssetToWorldMessageBox = DependencyManager::get()->createMessageBox(OffscreenUi::ICON_INFORMATION, + _addAssetToWorldMessageBox = getOffscreenUI()->createMessageBox(OffscreenUi::ICON_INFORMATION, "Downloading Model", "", QMessageBox::NoButton, QMessageBox::NoButton); connect(_addAssetToWorldMessageBox, SIGNAL(destroyed()), this, SLOT(onAssetToWorldMessageBoxClosed())); } @@ -8274,6 +8340,8 @@ DisplayPluginPointer Application::getActiveDisplayPlugin() const { return _displayPlugin; } + +#if !defined(DISABLE_QML) static const char* EXCLUSION_GROUP_KEY = "exclusionGroup"; static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, int index, bool active) { @@ -8314,6 +8382,7 @@ static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, in action->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(displayPluginGroup)); Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, name)); } +#endif void Application::updateDisplayMode() { // Unsafe to call this method from anything but the main thread @@ -8358,8 +8427,8 @@ void Application::setDisplayPlugin(DisplayPluginPointer newDisplayPlugin) { // instead emit a signal that the display plugin is changing and let // the desktop lock itself. Reduces coupling between the UI and display // plugins - auto offscreenUi = DependencyManager::get(); - auto desktop = offscreenUi->getDesktop(); + auto offscreenUi = getOffscreenUI(); + auto desktop = offscreenUi ? offscreenUi->getDesktop() : nullptr; auto menu = Menu::getInstance(); // Make the switch atomic from the perspective of other threads @@ -8405,7 +8474,9 @@ void Application::setDisplayPlugin(DisplayPluginPointer newDisplayPlugin) { } } - offscreenUi->resize(fromGlm(newDisplayPlugin->getRecommendedUiSize())); + if (offscreenUi) { + offscreenUi->resize(fromGlm(newDisplayPlugin->getRecommendedUiSize())); + } getApplicationCompositor().setDisplayPlugin(newDisplayPlugin); _displayPlugin = newDisplayPlugin; connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent, Qt::DirectConnection); diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index a87caeb9a8..646cc53cc0 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -156,12 +156,14 @@ void Application::paintGL() { renderArgs._blitFramebuffer.reset(); renderArgs._context->enableStereo(false); +#if !defined(DISABLE_QML) { auto stats = Stats::getInstance(); if (stats) { stats->setRenderDetails(renderArgs._details); } } +#endif uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin; _frameTimingsScriptingInterface.addValue(lastPaintDuration); diff --git a/interface/src/ConnectionMonitor.cpp b/interface/src/ConnectionMonitor.cpp index e86061b090..33d9fddc1b 100644 --- a/interface/src/ConnectionMonitor.cpp +++ b/interface/src/ConnectionMonitor.cpp @@ -48,7 +48,9 @@ void ConnectionMonitor::init() { emit setRedirectErrorState(REDIRECT_HIFI_ADDRESS, "", 5); } else { qDebug() << "ConnectionMonitor: Showing connection failure window"; +#if !defined(DISABLE_QML) DependencyManager::get()->setDomainConnectionFailureVisibility(true); +#endif } }); } @@ -59,8 +61,10 @@ void ConnectionMonitor::startTimer() { void ConnectionMonitor::stopTimer() { _timer.stop(); +#if !defined(DISABLE_QML) bool enableInterstitial = DependencyManager::get()->getDomainHandler().getInterstitialModeEnabled(); if (!enableInterstitial) { DependencyManager::get()->setDomainConnectionFailureVisibility(false); } +#endif } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 2fb40c8c30..26781631db 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -83,7 +83,9 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { // Now render the overlay components together into a single texture renderDomainConnectionStatusBorder(renderArgs); // renders the connected domain line renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope +#if !defined(DISABLE_QML) renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture, and the text overlays from scripts +#endif }); renderArgs->_batch = nullptr; // so future users of renderArgs don't try to use our batch diff --git a/interface/src/ui/OverlayConductor.cpp b/interface/src/ui/OverlayConductor.cpp index da4fdaba44..8edd8ee3a5 100644 --- a/interface/src/ui/OverlayConductor.cpp +++ b/interface/src/ui/OverlayConductor.cpp @@ -74,6 +74,7 @@ void OverlayConductor::centerUI() { } void OverlayConductor::update(float dt) { +#if !defined(DISABLE_QML) auto offscreenUi = DependencyManager::get(); if (!offscreenUi) { return; @@ -115,4 +116,5 @@ void OverlayConductor::update(float dt) { if (shouldRecenter && !_suppressedByHead) { centerUI(); } +#endif } diff --git a/interface/src/ui/OverlayConductor.h b/interface/src/ui/OverlayConductor.h index b47e23d28a..6c3732cf3c 100644 --- a/interface/src/ui/OverlayConductor.h +++ b/interface/src/ui/OverlayConductor.h @@ -25,8 +25,10 @@ private: bool headOutsideOverlay() const; bool updateAvatarIsAtRest(); +#if !defined(DISABLE_QML) bool _suppressedByHead { false }; bool _hmdMode { false }; +#endif // used by updateAvatarIsAtRest uint64_t _desiredAtRestTimer { 0 }; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 22b123c85d..17b0895f47 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -232,11 +232,15 @@ OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties) */ if (type == ImageOverlay::TYPE) { +#if !defined(DISABLE_QML) thisOverlay = Overlay::Pointer(new ImageOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); +#endif } else if (type == Image3DOverlay::TYPE || type == "billboard") { // "billboard" for backwards compatibility thisOverlay = Overlay::Pointer(new Image3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); } else if (type == TextOverlay::TYPE) { +#if !defined(DISABLE_QML) thisOverlay = Overlay::Pointer(new TextOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); +#endif } else if (type == Text3DOverlay::TYPE) { thisOverlay = Overlay::Pointer(new Text3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); } else if (type == Shape3DOverlay::TYPE) { diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index da877f7b3b..978732fd50 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -27,16 +27,16 @@ class Dependency { public: typedef std::function DeleterFunction; - + protected: virtual ~Dependency() {} virtual void customDeleter() { _customDeleter(this); } - + void setCustomDeleter(DeleterFunction customDeleter) { _customDeleter = customDeleter; } DeleterFunction _customDeleter = [](Dependency* pointer) { delete pointer; }; - + friend class DependencyManager; }; @@ -49,10 +49,10 @@ class DependencyManager { public: template static QSharedPointer get(); - + template static bool isSet(); - + template static QSharedPointer set(Args&&... args); @@ -61,10 +61,10 @@ public: template static void destroy(); - + template static void registerInheritance(); - + template static size_t typeHash() { #ifdef Q_OS_ANDROID @@ -79,9 +79,9 @@ private: template size_t getHashCode(); - + QSharedPointer& safeGet(size_t hashCode); - + QHash> _instanceHash; QHash _inheritanceHash; }; @@ -90,15 +90,17 @@ template QSharedPointer DependencyManager::get() { static size_t hashCode = manager().getHashCode(); static QWeakPointer instance; - + if (instance.isNull()) { instance = qSharedPointerCast(manager().safeGet(hashCode)); - + +#ifndef QT_NO_DEBUG if (instance.isNull()) { qWarning() << "DependencyManager::get(): No instance available for" << typeid(T).name(); } +#endif } - + return instance.toStrongRef(); } @@ -159,12 +161,12 @@ template size_t DependencyManager::getHashCode() { size_t hashCode = typeHash(); auto derivedHashCode = _inheritanceHash.find(hashCode); - + while (derivedHashCode != _inheritanceHash.end()) { hashCode = derivedHashCode.value(); derivedHashCode = _inheritanceHash.find(hashCode); } - + return hashCode; } diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 0aad297587..a13bdf0657 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -616,7 +616,9 @@ bool OffscreenUi::navigationFocused() { } void OffscreenUi::setNavigationFocused(bool focused) { - offscreenFlags->setNavigationFocused(focused); + if (offscreenFlags) { + offscreenFlags->setNavigationFocused(focused); + } } // FIXME HACK.... diff --git a/libraries/ui/src/ui/Menu.cpp b/libraries/ui/src/ui/Menu.cpp index 848b2362ee..b3b76ab534 100644 --- a/libraries/ui/src/ui/Menu.cpp +++ b/libraries/ui/src/ui/Menu.cpp @@ -422,9 +422,11 @@ void Menu::removeMenu(const QString& menuName) { } else { QMenuBar::removeAction(action); auto offscreenUi = DependencyManager::get(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->removeAction(action); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->removeAction(action); + }); + } } QMenuBar::repaint(); @@ -532,9 +534,11 @@ void Menu::setGroupingIsVisible(const QString& grouping, bool isVisible) { MenuWrapper::MenuWrapper(ui::Menu& rootMenu, QMenu* menu) : _rootMenu(rootMenu), _realMenu(menu) { auto offscreenUi = DependencyManager::get(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->addMenu(menu); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->addMenu(menu); + }); + } _rootMenu._backMap[menu] = this; } @@ -553,50 +557,62 @@ void MenuWrapper::setEnabled(bool enabled) { QAction* MenuWrapper::addSeparator() { QAction* action = _realMenu->addSeparator(); auto offscreenUi = DependencyManager::get(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->addSeparator(_realMenu); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->addSeparator(_realMenu); + }); + } return action; } void MenuWrapper::addAction(QAction* action) { _realMenu->addAction(action); auto offscreenUi = DependencyManager::get(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->addAction(_realMenu, action); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->addAction(_realMenu, action); + }); + } } QAction* MenuWrapper::addAction(const QString& menuName) { QAction* action = _realMenu->addAction(menuName); auto offscreenUi = DependencyManager::get(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->addAction(_realMenu, action); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->addAction(_realMenu, action); + }); + } return action; } QAction* MenuWrapper::addAction(const QString& menuName, const QObject* receiver, const char* member, const QKeySequence& shortcut) { QAction* action = _realMenu->addAction(menuName, receiver, member, shortcut); auto offscreenUi = DependencyManager::get(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->addAction(_realMenu, action); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->addAction(_realMenu, action); + }); + } return action; } void MenuWrapper::removeAction(QAction* action) { _realMenu->removeAction(action); auto offscreenUi = DependencyManager::get(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->removeAction(action); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->removeAction(action); + }); + } } void MenuWrapper::insertAction(QAction* before, QAction* action) { _realMenu->insertAction(before, action); auto offscreenUi = DependencyManager::get(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->insertAction(before, action); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->insertAction(before, action); + }); + } } diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index 8fc2d069ec..13b0498e76 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -366,6 +366,7 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { auto offscreenUi = DependencyManager::get(); if (toolbarMode) { +#if !defined(DISABLE_QML) // create new desktop window auto tabletRootWindow = new TabletRootWindow(); tabletRootWindow->initQml(QVariantMap()); @@ -379,6 +380,7 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { // forward qml surface events to interface js connect(tabletRootWindow, &QmlWindowClass::fromQml, this, &TabletProxy::fromQml); +#endif } else { if (_currentPathLoaded != TABLET_HOME_SOURCE_URL) { loadHomeScreen(true); From a4175b042891b7b807273582b806d8ec364a60b7 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 27 Nov 2018 14:17:28 -0800 Subject: [PATCH 13/13] Error handling in checkout --- interface/resources/qml/hifi/commerce/checkout/Checkout.qml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 6320cd1675..7e17d20375 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -1080,6 +1080,12 @@ Rectangle { // function updateCheckoutQMLFromHTTP(error, result) { + if (error || (result.status !== 'success')) { + // The QML will display a loading spinner forever if the user is stuck here. + console.log("Error in Checkout.qml when getting marketplace item info!"); + return; + } + root.itemInfoReceived = true; root.itemName = result.data.title; root.itemPrice = result.data.cost;