Unified · Split
| @@ -9,6 +9,8 @@ · 8 unmodified lines | |||
| 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html | 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html |
| 10 | // | 10 | // |
| 11 | 11 | ||
| 12 | #include "AudioMixer.h" | ||
| 13 | |||
| 12 | #include <thread> | 14 | #include <thread> |
| 13 | 15 | ||
| 14 | #include <QtCore/QJsonArray> | 16 | #include <QtCore/QJsonArray> |
| @@ -36,8 +38,6 @@ · 21 unmodified lines | |||
| 36 | #include "AvatarAudioStream.h" | 38 | #include "AvatarAudioStream.h" |
| 37 | #include "InjectedAudioStream.h" | 39 | #include "InjectedAudioStream.h" |
| 38 | 40 | ||
| 39 | #include "AudioMixer.h" | ||
| 40 | |||
| 41 | static const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.5f; // attenuation = -6dB * log2(distance) | 41 | static const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.5f; // attenuation = -6dB * log2(distance) |
| 42 | static const int DISABLE_STATIC_JITTER_FRAMES = -1; | 42 | static const int DISABLE_STATIC_JITTER_FRAMES = -1; |
| 43 | static const float DEFAULT_NOISE_MUTING_THRESHOLD = 1.0f; | 43 | static const float DEFAULT_NOISE_MUTING_THRESHOLD = 1.0f; |
| @@ -18,6 +18,8 @@ · 17 unmodified lines | |||
| 18 | #include <ThreadedAssignment.h> | 18 | #include <ThreadedAssignment.h> |
| 19 | #include <UUIDHasher.h> | 19 | #include <UUIDHasher.h> |
| 20 | 20 | ||
| 21 | #include <plugins/Forward.h> | ||
| 22 | |||
| 21 | #include "AudioMixerStats.h" | 23 | #include "AudioMixerStats.h" |
| 22 | #include "AudioMixerSlavePool.h" | 24 | #include "AudioMixerSlavePool.h" |
| 23 | 25 | ||
| @@ -9,6 +9,8 @@ · 8 unmodified lines | |||
| 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html | 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html |
| 10 | // | 10 | // |
| 11 | 11 | ||
| 12 | #include "AudioMixerClientData.h" | ||
| 13 | |||
| 12 | #include <random> | 14 | #include <random> |
| 13 | 15 | ||
| 14 | #include <QtCore/QDebug> | 16 | #include <QtCore/QDebug> |
| @@ -22,8 +24,6 @@ · 7 unmodified lines | |||
| 22 | #include "AudioLogging.h" | 24 | #include "AudioLogging.h" |
| 23 | #include "AudioHelpers.h" | 25 | #include "AudioHelpers.h" |
| 24 | #include "AudioMixer.h" | 26 | #include "AudioMixer.h" |
| 25 | #include "AudioMixerClientData.h" | ||
| 26 | |||
| 27 | 27 | ||
| 28 | AudioMixerClientData::AudioMixerClientData(const QUuid& nodeID) : | 28 | AudioMixerClientData::AudioMixerClientData(const QUuid& nodeID) : |
| 29 | NodeData(nodeID), | 29 | NodeData(nodeID), |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | |||
| 21 | #include <AudioLimiter.h> | 21 | #include <AudioLimiter.h> |
| 22 | #include <UUIDHasher.h> | 22 | #include <UUIDHasher.h> |
| 23 | 23 | ||
| 24 | #include <plugins/Forward.h> | ||
| 24 | #include <plugins/CodecPlugin.h> | 25 | #include <plugins/CodecPlugin.h> |
| 25 | 26 | ||
| 26 | #include "PositionalAudioStream.h" | 27 | #include "PositionalAudioStream.h" |
| @@ -9,6 +9,8 @@ · 8 unmodified lines | |||
| 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html | 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html |
| 10 | // | 10 | // |
| 11 | 11 | ||
| 12 | #include "AudioMixerSlave.h" | ||
| 13 | |||
| 12 | #include <algorithm> | 14 | #include <algorithm> |
| 13 | 15 | ||
| 14 | #include <glm/glm.hpp> | 16 | #include <glm/glm.hpp> |
| @@ -34,8 +36,6 @@ · 19 unmodified lines | |||
| 34 | #include "InjectedAudioStream.h" | 36 | #include "InjectedAudioStream.h" |
| 35 | #include "AudioHelpers.h" | 37 | #include "AudioHelpers.h" |
| 36 | 38 | ||
| 37 | #include "AudioMixerSlave.h" | ||
| 38 | |||
| 39 | using AudioStreamMap = AudioMixerClientData::AudioStreamMap; | 39 | using AudioStreamMap = AudioMixerClientData::AudioStreamMap; |
| 40 | 40 | ||
| 41 | // packet helpers | 41 | // packet helpers |
Binary file not shown.
| @@ -14,8 +14,8 @@ import "../styles-uit" · 13 unmodified lines | |||
| 14 | Item { | 14 | Item { |
| 15 | property int colorScheme: 0; | 15 | property int colorScheme: 0; |
| 16 | 16 | ||
| 17 | readonly property var topColor: [ hifi.colors.baseGrayShadow, hifi.colors.faintGray ]; | 17 | readonly property var topColor: [ hifi.colors.baseGrayShadow, hifi.colors.faintGray, "#89858C" ]; |
| 18 | readonly property var bottomColor: [ hifi.colors.baseGrayHighlight, hifi.colors.faintGray ]; | 18 | readonly property var bottomColor: [ hifi.colors.baseGrayHighlight, hifi.colors.faintGray, "#89858C" ]; |
| 19 | 19 | ||
| 20 | // Size | 20 | // Size |
| 21 | height: colorScheme === 0 ? 2 : 1; | 21 | height: colorScheme === 0 ? 2 : 1; |
| @@ -34,11 +34,10 @@ TextField { · 33 unmodified lines | |||
| 34 | 34 | ||
| 35 | placeholderText: textField.placeholderText | 35 | placeholderText: textField.placeholderText |
| 36 | 36 | ||
| 37 | FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; } | 37 | FontLoader { id: firaSansRegular; source: "../../fonts/FiraSans-Regular.ttf"; } |
| 38 | FontLoader { id: hifiGlyphs; source: "../../fonts/hifi-glyphs.ttf"; } | 38 | FontLoader { id: hifiGlyphs; source: "../../fonts/hifi-glyphs.ttf"; } |
| 39 | font.family: firaSansSemiBold.name | 39 | font.family: firaSansRegular.name |
| 40 | font.pixelSize: hifi.fontSizes.textFieldInput | 40 | font.pixelSize: hifi.fontSizes.textFieldInput |
| 41 | font.italic: textField.text == "" | ||
| 42 | height: implicitHeight + 3 // Make surrounding box higher so that highlight is vertically centered. | 41 | height: implicitHeight + 3 // Make surrounding box higher so that highlight is vertically centered. |
| 43 | property alias textFieldLabel: textFieldLabel | 42 | property alias textFieldLabel: textFieldLabel |
| 44 | 43 | ||
| @@ -28,7 +28,7 @@ Rectangle { · 27 unmodified lines | |||
| 28 | id: root; | 28 | id: root; |
| 29 | objectName: "checkout" | 29 | objectName: "checkout" |
| 30 | property string activeView: "initialize"; | 30 | property string activeView: "initialize"; |
| 31 | property bool purchasesReceived: false; | 31 | property bool ownershipStatusReceived: false; |
| 32 | property bool balanceReceived: false; | 32 | property bool balanceReceived: false; |
| 33 | property string itemName; | 33 | property string itemName; |
| 34 | property string itemId; | 34 | property string itemId; |
| @@ -37,11 +37,16 @@ Rectangle { · 2 unmodified lines | |||
| 37 | property double balanceAfterPurchase; | 37 | property double balanceAfterPurchase; |
| 38 | property bool alreadyOwned: false; | 38 | property bool alreadyOwned: false; |
| 39 | property int itemPrice: -1; | 39 | property int itemPrice: -1; |
| 40 | property bool itemIsJson: true; | 40 | property bool isCertified; |
| 41 | property string itemType; | ||
| 42 | property var itemTypesArray: ["entity", "wearable", "contentSet", "app", "avatar"]; | ||
| 43 | property var itemTypesText: ["entity", "wearable", "content set", "app", "avatar"]; | ||
| 44 | property var buttonTextNormal: ["REZ", "WEAR", "REPLACE CONTENT SET", "INSTALL", "WEAR"]; | ||
| 45 | property var buttonTextClicked: ["REZZED!", "WORN!", "CONTENT SET REPLACED!", "INSTALLED!", "AVATAR CHANGED!"] | ||
| 46 | property var buttonGlyph: [hifi.glyphs.wand, hifi.glyphs.hat, hifi.glyphs.globe, hifi.glyphs.install, hifi.glyphs.avatar]; | ||
| 41 | property bool shouldBuyWithControlledFailure: false; | 47 | property bool shouldBuyWithControlledFailure: false; |
| 42 | property bool debugCheckoutSuccess: false; | 48 | property bool debugCheckoutSuccess: false; |
| 43 | property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified(); | 49 | property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified(); |
| 44 | property bool isWearable; | ||
| 45 | property string referrer; | 50 | property string referrer; |
| 46 | // Style | 51 | // Style |
| 47 | color: hifi.colors.white; | 52 | color: hifi.colors.white; |
| @@ -85,7 +90,9 @@ Rectangle { · 37 unmodified lines | |||
| 85 | UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned, result.message); | 90 | UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned, result.message); |
| 86 | } else { | 91 | } else { |
| 87 | root.itemHref = result.data.download_url; | 92 | root.itemHref = result.data.download_url; |
| 88 | root.isWearable = result.data.categories.indexOf("Wearables") > -1; | 93 | if (result.data.categories.indexOf("Wearables") > -1) { |
| 94 | root.itemType = "wearable"; | ||
| 95 | } | ||
| 89 | root.activeView = "checkoutSuccess"; | 96 | root.activeView = "checkoutSuccess"; |
| 90 | UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned); | 97 | UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned); |
| 91 | } | 98 | } |
| @@ -97,32 +104,53 @@ Rectangle { · 5 unmodified lines | |||
| 97 | } else { | 104 | } else { |
| 98 | root.balanceReceived = true; | 105 | root.balanceReceived = true; |
| 99 | root.balanceAfterPurchase = result.data.balance - root.itemPrice; | 106 | root.balanceAfterPurchase = result.data.balance - root.itemPrice; |
| 100 | root.setBuyText(); | 107 | root.refreshBuyUI(); |
| 101 | } | 108 | } |
| 102 | } | 109 | } |
| 103 | 110 | ||
| 104 | onInventoryResult: { | 111 | onAlreadyOwnedResult: { |
| 105 | if (result.status !== 'success') { | 112 | if (result.status !== 'success') { |
| 106 | console.log("Failed to get purchases", result.data.message); | 113 | console.log("Failed to get Already Owned status", result.data.message); |
| 107 | } else { | 114 | } else { |
| 108 | root.purchasesReceived = true; | 115 | root.ownershipStatusReceived = true; |
| 109 | if (purchasesContains(result.data.assets, itemId)) { | 116 | if (result.data.marketplace_item_id === root.itemId) { |
| 110 | root.alreadyOwned = true; | 117 | root.alreadyOwned = result.data.already_owned; |
| 111 | } else { | 118 | } else { |
| 119 | console.log("WARNING - Received 'Already Owned' status about different Marketplace ID!"); | ||
| 112 | root.alreadyOwned = false; | 120 | root.alreadyOwned = false; |
| 113 | } | 121 | } |
| 114 | root.setBuyText(); | 122 | root.refreshBuyUI(); |
| 115 | } | 123 | } |
| 116 | } | 124 | } |
| 117 | } | 125 | } |
| 118 | 126 | ||
| 119 | onItemIdChanged: { | 127 | onItemIdChanged: { |
| 120 | Commerce.inventory(); | 128 | root.ownershipStatusReceived = false; |
| 129 | Commerce.alreadyOwned(root.itemId); | ||
| 121 | itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg"; | 130 | itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg"; |
| 122 | } | 131 | } |
| 123 | 132 | ||
| 124 | onItemHrefChanged: { | 133 | onItemHrefChanged: { |
| 125 | itemIsJson = root.itemHref.endsWith('.json'); | 134 | if (root.itemHref.indexOf(".fst") > -1) { |
| 135 | root.itemType = "avatar"; | ||
| 136 | } else if (root.itemHref.indexOf('.json.gz') > -1) { | ||
| 137 | root.itemType = "contentSet"; | ||
| 138 | } else if (root.itemHref.indexOf('.app.json') > -1) { | ||
| 139 | root.itemType = "app"; | ||
| 140 | } else if (root.itemHref.indexOf('.json') > -1) { | ||
| 141 | root.itemType = "entity"; // "wearable" type handled later | ||
| 142 | } else { | ||
| 143 | console.log("WARNING - Item type is UNKNOWN!"); | ||
| 144 | root.itemType = "entity"; | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | onItemTypeChanged: { | ||
| 149 | if (root.itemType === "entity" || root.itemType === "wearable" || root.itemType === "contentSet" || root.itemType === "avatar") { | ||
| 150 | root.isCertified = true; | ||
| 151 | } else { | ||
| 152 | root.isCertified = false; | ||
| 153 | } | ||
| 126 | } | 154 | } |
| 127 | 155 | ||
| 128 | onItemPriceChanged: { | 156 | onItemPriceChanged: { |
| @@ -203,7 +231,7 @@ Rectangle { · 74 unmodified lines | |||
| 203 | color: hifi.colors.white; | 231 | color: hifi.colors.white; |
| 204 | 232 | ||
| 205 | Component.onCompleted: { | 233 | Component.onCompleted: { |
| 206 | purchasesReceived = false; | 234 | ownershipStatusReceived = false; |
| 207 | balanceReceived = false; | 235 | balanceReceived = false; |
| 208 | Commerce.getWalletStatus(); | 236 | Commerce.getWalletStatus(); |
| 209 | } | 237 | } |
| @@ -278,6 +306,31 @@ Rectangle { · 68 unmodified lines | |||
| 278 | anchors.left: parent.left; | 306 | anchors.left: parent.left; |
| 279 | anchors.right: parent.right; | 307 | anchors.right: parent.right; |
| 280 | 308 | ||
| 309 | Rectangle { | ||
| 310 | id: loading; | ||
| 311 | z: 997; | ||
| 312 | visible: !root.ownershipStatusReceived || !root.balanceReceived; | ||
| 313 | anchors.fill: parent; | ||
| 314 | color: Qt.rgba(0.0, 0.0, 0.0, 0.7); | ||
| 315 | |||
| 316 | // This object is always used in a popup. | ||
| 317 | // This MouseArea is used to prevent a user from being | ||
| 318 | // able to click on a button/mouseArea underneath the popup/section. | ||
| 319 | MouseArea { | ||
| 320 | anchors.fill: parent; | ||
| 321 | hoverEnabled: true; | ||
| 322 | propagateComposedEvents: false; | ||
| 323 | } | ||
| 324 | |||
| 325 | AnimatedImage { | ||
| 326 | source: "../common/images/loader.gif" | ||
| 327 | width: 96; | ||
| 328 | height: width; | ||
| 329 | anchors.verticalCenter: parent.verticalCenter; | ||
| 330 | anchors.horizontalCenter: parent.horizontalCenter; | ||
| 331 | } | ||
| 332 | } | ||
| 333 | |||
| 281 | RalewayRegular { | 334 | RalewayRegular { |
| 282 | id: confirmPurchaseText; | 335 | id: confirmPurchaseText; |
| 283 | anchors.top: parent.top; | 336 | anchors.top: parent.top; |
| @@ -286,8 +339,8 @@ Rectangle { · 2 unmodified lines | |||
| 286 | anchors.leftMargin: 16; | 339 | anchors.leftMargin: 16; |
| 287 | width: paintedWidth; | 340 | width: paintedWidth; |
| 288 | height: paintedHeight; | 341 | height: paintedHeight; |
| 289 | text: "Confirm Purchase:"; | 342 | text: "Review Purchase:"; |
| 290 | color: hifi.colors.baseGray; | 343 | color: hifi.colors.black; |
| 291 | size: 28; | 344 | size: 28; |
| 292 | } | 345 | } |
| 293 | 346 | ||
| @@ -400,7 +453,7 @@ Rectangle { · 106 unmodified lines | |||
| 400 | width: root.width; | 453 | width: root.width; |
| 401 | // Anchors | 454 | // Anchors |
| 402 | anchors.top: separator2.bottom; | 455 | anchors.top: separator2.bottom; |
| 403 | anchors.topMargin: 16; | 456 | anchors.topMargin: 0; |
| 404 | anchors.left: parent.left; | 457 | anchors.left: parent.left; |
| 405 | anchors.leftMargin: 16; | 458 | anchors.leftMargin: 16; |
| 406 | anchors.right: parent.right; | 459 | anchors.right: parent.right; |
| @@ -411,8 +464,8 @@ Rectangle { · 4 unmodified lines | |||
| 411 | Rectangle { | 464 | Rectangle { |
| 412 | id: buyTextContainer; | 465 | id: buyTextContainer; |
| 413 | visible: buyText.text !== ""; | 466 | visible: buyText.text !== ""; |
| 414 | anchors.top: cancelPurchaseButton.bottom; | 467 | anchors.top: parent.top; |
| 415 | anchors.topMargin: 16; | 468 | anchors.topMargin: 10; |
| 416 | anchors.left: parent.left; | 469 | anchors.left: parent.left; |
| 417 | anchors.right: parent.right; | 470 | anchors.right: parent.right; |
| 418 | height: buyText.height + 30; | 471 | height: buyText.height + 30; |
| @@ -454,32 +507,63 @@ Rectangle { · 35 unmodified lines | |||
| 454 | // Alignment | 507 | // Alignment |
| 455 | horizontalAlignment: Text.AlignLeft; | 508 | horizontalAlignment: Text.AlignLeft; |
| 456 | verticalAlignment: Text.AlignVCenter; | 509 | verticalAlignment: Text.AlignVCenter; |
| 510 | } | ||
| 511 | } | ||
| 457 | 512 | ||
| 458 | onLinkActivated: { | 513 | // "View in My Purchases" button |
| 459 | sendToScript({method: 'checkout_goToPurchases', filterText: root.itemName}); | 514 | HifiControlsUit.Button { |
| 460 | } | 515 | id: viewInMyPurchasesButton; |
| 516 | visible: false; | ||
| 517 | color: hifi.buttons.blue; | ||
| 518 | colorScheme: hifi.colorSchemes.light; | ||
| 519 | anchors.top: buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top; | ||
| 520 | anchors.topMargin: 10; | ||
| 521 | height: 50; | ||
| 522 | anchors.left: parent.left; | ||
| 523 | anchors.right: parent.right; | ||
| 524 | text: "VIEW THIS ITEM IN MY PURCHASES"; | ||
| 525 | onClicked: { | ||
| 526 | sendToScript({method: 'checkout_goToPurchases', filterText: root.itemName}); | ||
| 461 | } | 527 | } |
| 462 | } | 528 | } |
| 463 | 529 | ||
| 464 | // "Buy" button | 530 | // "Buy" button |
| 465 | HifiControlsUit.Button { | 531 | HifiControlsUit.Button { |
| 466 | id: buyButton; | 532 | id: buyButton; |
| 467 | enabled: (root.balanceAfterPurchase >= 0 && purchasesReceived && balanceReceived) || !itemIsJson; | 533 | visible: !((root.itemType === "avatar" || root.itemType === "app") && viewInMyPurchasesButton.visible) |
| 468 | color: hifi.buttons.blue; | 534 | enabled: (root.balanceAfterPurchase >= 0 && ownershipStatusReceived && balanceReceived) || (!root.isCertified); |
| 535 | color: viewInMyPurchasesButton.visible ? hifi.buttons.white : hifi.buttons.blue; | ||
| 469 | colorScheme: hifi.colorSchemes.light; | 536 | colorScheme: hifi.colorSchemes.light; |
| 470 | anchors.top: checkoutActionButtonsContainer.top; | 537 | anchors.top: viewInMyPurchasesButton.visible ? viewInMyPurchasesButton.bottom : |
| 471 | anchors.topMargin: 16; | 538 | (buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top); |
| 472 | height: 40; | 539 | anchors.topMargin: 10; |
| 540 | height: 50; | ||
| 473 | anchors.left: parent.left; | 541 | anchors.left: parent.left; |
| 474 | anchors.right: parent.right; | 542 | anchors.right: parent.right; |
| 475 | text: (itemIsJson ? ((purchasesReceived && balanceReceived) ? "Confirm Purchase" : "--") : "Get Item"); | 543 | text: ((root.isCertified) ? ((ownershipStatusReceived && balanceReceived) ? |
| 544 | (viewInMyPurchasesButton.visible ? "Buy It Again" : "Confirm Purchase") : "--") : "Get Item"); | ||
| 476 | onClicked: { | 545 | onClicked: { |
| 477 | if (itemIsJson) { | 546 | if (root.isCertified) { |
| 478 | buyButton.enabled = false; | ||
| 479 | if (!root.shouldBuyWithControlledFailure) { | 547 | if (!root.shouldBuyWithControlledFailure) { |
| 480 | Commerce.buy(itemId, itemPrice); | 548 | if (root.itemType === "contentSet" && !Entities.canReplaceContent()) { |
| 549 | lightboxPopup.titleText = "Purchase Content Set"; | ||
| 550 | lightboxPopup.bodyText = "You will not be able to replace this domain's content with <b>" + root.itemName + | ||
| 551 | " </b>until the server owner gives you 'Replace Content' permissions.<br><br>Are you sure you want to purchase this content set?"; | ||
| 552 | lightboxPopup.button1text = "CANCEL"; | ||
| 553 | lightboxPopup.button1method = "root.visible = false;" | ||
| 554 | lightboxPopup.button2text = "CONFIRM"; | ||
| 555 | lightboxPopup.button2method = "Commerce.buy('" + root.itemId + "', " + root.itemPrice + ");" + | ||
| 556 | "root.visible = false; buyButton.enabled = false; loading.visible = true;"; | ||
| 557 | lightboxPopup.visible = true; | ||
| 558 | } else { | ||
| 559 | buyButton.enabled = false; | ||
| 560 | loading.visible = true; | ||
| 561 | Commerce.buy(root.itemId, root.itemPrice); | ||
| 562 | } | ||
| 481 | } else { | 563 | } else { |
| 482 | Commerce.buy(itemId, itemPrice, true); | 564 | buyButton.enabled = false; |
| 565 | loading.visible = true; | ||
| 566 | Commerce.buy(root.itemId, root.itemPrice, true); | ||
| 483 | } | 567 | } |
| 484 | } else { | 568 | } else { |
| 485 | if (urlHandler.canHandleUrl(itemHref)) { | 569 | if (urlHandler.canHandleUrl(itemHref)) { |
| @@ -494,9 +578,9 @@ Rectangle { · 8 unmodified lines | |||
| 494 | id: cancelPurchaseButton; | 578 | id: cancelPurchaseButton; |
| 495 | color: hifi.buttons.noneBorderlessGray; | 579 | color: hifi.buttons.noneBorderlessGray; |
| 496 | colorScheme: hifi.colorSchemes.light; | 580 | colorScheme: hifi.colorSchemes.light; |
| 497 | anchors.top: buyButton.bottom; | 581 | anchors.top: buyButton.visible ? buyButton.bottom : viewInMyPurchasesButton.bottom; |
| 498 | anchors.topMargin: 16; | 582 | anchors.topMargin: 10; |
| 499 | height: 40; | 583 | height: 50; |
| 500 | anchors.left: parent.left; | 584 | anchors.left: parent.left; |
| 501 | anchors.right: parent.right; | 585 | anchors.right: parent.right; |
| 502 | text: "Cancel" | 586 | text: "Cancel" |
| @@ -522,31 +606,32 @@ Rectangle { · 19 unmodified lines | |||
| 522 | anchors.top: titleBarContainer.bottom; | 606 | anchors.top: titleBarContainer.bottom; |
| 523 | anchors.bottom: root.bottom; | 607 | anchors.bottom: root.bottom; |
| 524 | anchors.left: parent.left; | 608 | anchors.left: parent.left; |
| 525 | anchors.leftMargin: 16; | 609 | anchors.leftMargin: 20; |
| 526 | anchors.right: parent.right; | 610 | anchors.right: parent.right; |
| 527 | anchors.rightMargin: 16; | 611 | anchors.rightMargin: 20; |
| 528 | 612 | ||
| 529 | RalewayRegular { | 613 | RalewayRegular { |
| 530 | id: completeText; | 614 | id: completeText; |
| 531 | anchors.top: parent.top; | 615 | anchors.top: parent.top; |
| 532 | anchors.topMargin: 30; | 616 | anchors.topMargin: 18; |
| 533 | anchors.left: parent.left; | 617 | anchors.left: parent.left; |
| 534 | width: paintedWidth; | 618 | width: paintedWidth; |
| 535 | height: paintedHeight; | 619 | height: paintedHeight; |
| 536 | text: "Thank you for your order!"; | 620 | text: "Thank you for your order!"; |
| 537 | color: hifi.colors.baseGray; | 621 | color: hifi.colors.baseGray; |
| 538 | size: 28; | 622 | size: 36; |
| 539 | } | 623 | } |
| 540 | 624 | ||
| 541 | RalewaySemiBold { | 625 | RalewaySemiBold { |
| 542 | id: completeText2; | 626 | id: completeText2; |
| 543 | text: "The item " + '<font color="' + hifi.colors.blueAccent + '"><a href="#">' + root.itemName + '</a></font>' + | 627 | text: "The " + (root.itemTypesText)[itemTypesArray.indexOf(root.itemType)] + |
| 544 | " has been added to your Purchases and a receipt will appear in your Wallet's transaction history."; | 628 | ' <font color="' + hifi.colors.blueAccent + '"><a href="#">' + root.itemName + '</a></font>' + |
| 629 | " has been added to your Purchases and a receipt will appear in your Wallet's transaction history."; | ||
| 545 | // Text size | 630 | // Text size |
| 546 | size: 20; | 631 | size: 18; |
| 547 | // Anchors | 632 | // Anchors |
| 548 | anchors.top: completeText.bottom; | 633 | anchors.top: completeText.bottom; |
| 549 | anchors.topMargin: 10; | 634 | anchors.topMargin: 15; |
| 550 | height: paintedHeight; | 635 | height: paintedHeight; |
| 551 | anchors.left: parent.left; | 636 | anchors.left: parent.left; |
| 552 | anchors.right: parent.right; | 637 | anchors.right: parent.right; |
| @@ -576,7 +661,7 @@ Rectangle { · 23 unmodified lines | |||
| 576 | 661 | ||
| 577 | RalewayBold { | 662 | RalewayBold { |
| 578 | anchors.fill: parent; | 663 | anchors.fill: parent; |
| 579 | text: "REZZED"; | 664 | text: (root.buttonTextClicked)[itemTypesArray.indexOf(root.itemType)]; |
| 580 | size: 18; | 665 | size: 18; |
| 581 | color: hifi.colors.white; | 666 | color: hifi.colors.white; |
| 582 | verticalAlignment: Text.AlignVCenter; | 667 | verticalAlignment: Text.AlignVCenter; |
| @@ -592,26 +677,52 @@ Rectangle { · 9 unmodified lines | |||
| 592 | // "Rez" button | 677 | // "Rez" button |
| 593 | HifiControlsUit.Button { | 678 | HifiControlsUit.Button { |
| 594 | id: rezNowButton; | 679 | id: rezNowButton; |
| 595 | enabled: root.canRezCertifiedItems || root.isWearable; | 680 | enabled: (root.itemType === "entity" && root.canRezCertifiedItems) || |
| 596 | buttonGlyph: hifi.glyphs.lightning; | 681 | (root.itemType === "contentSet" && Entities.canReplaceContent()) || |
| 682 | root.itemType === "wearable" || root.itemType === "avatar"; | ||
| 683 | buttonGlyph: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)]; | ||
| 597 | color: hifi.buttons.red; | 684 | color: hifi.buttons.red; |
| 598 | colorScheme: hifi.colorSchemes.light; | 685 | colorScheme: hifi.colorSchemes.light; |
| 599 | anchors.top: completeText2.bottom; | 686 | anchors.top: completeText2.bottom; |
| 600 | anchors.topMargin: 30; | 687 | anchors.topMargin: 27; |
| 601 | height: 50; | 688 | height: 50; |
| 602 | anchors.left: parent.left; | 689 | anchors.left: parent.left; |
| 603 | anchors.right: parent.right; | 690 | anchors.right: parent.right; |
| 604 | text: root.isWearable ? "Wear It" : "Rez It" | 691 | text: (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)]; |
| 605 | onClicked: { | 692 | onClicked: { |
| 606 | sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable}); | 693 | if (root.itemType === "contentSet") { |
| 607 | rezzedNotifContainer.visible = true; | 694 | lightboxPopup.titleText = "Replace Content"; |
| 608 | rezzedNotifContainerTimer.start(); | 695 | lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain. " + |
| 609 | UserActivityLogger.commerceEntityRezzed(root.itemId, "checkout", root.isWearable ? "rez" : "wear"); | 696 | "If you want to save the state of the content in this domain, create a backup before proceeding.<br><br>" + |
| 697 | "For more information about backing up and restoring content, " + | ||
| 698 | "<a href='https://docs.highfidelity.com/create-and-explore/start-working-in-your-sandbox/restoring-sandbox-content'>" + | ||
| 699 | "click here to open info on your desktop browser."; | ||
| 700 | lightboxPopup.button1text = "CANCEL"; | ||
| 701 | lightboxPopup.button1method = "root.visible = false;" | ||
| 702 | lightboxPopup.button2text = "CONFIRM"; | ||
| 703 | lightboxPopup.button2method = "Commerce.replaceContentSet('" + root.itemHref + "');" + | ||
| 704 | "root.visible = false;rezzedNotifContainer.visible = true; rezzedNotifContainerTimer.start();" + | ||
| 705 | "UserActivityLogger.commerceEntityRezzed('" + root.itemId + "', 'checkout', '" + root.itemType + "');"; | ||
| 706 | lightboxPopup.visible = true; | ||
| 707 | } else if (root.itemType === "avatar") { | ||
| 708 | lightboxPopup.titleText = "Change Avatar"; | ||
| 709 | lightboxPopup.bodyText = "This will change your current avatar to " + root.itemName + " while retaining your wearables."; | ||
| 710 | lightboxPopup.button1text = "CANCEL"; | ||
| 711 | lightboxPopup.button1method = "root.visible = false;" | ||
| 712 | lightboxPopup.button2text = "CONFIRM"; | ||
| 713 | lightboxPopup.button2method = "MyAvatar.useFullAvatarURL('" + root.itemHref + "'); root.visible = false;"; | ||
| 714 | lightboxPopup.visible = true; | ||
| 715 | } else { | ||
| 716 | sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); | ||
| 717 | rezzedNotifContainer.visible = true; | ||
| 718 | rezzedNotifContainerTimer.start(); | ||
| 719 | UserActivityLogger.commerceEntityRezzed(root.itemId, "checkout", root.itemType); | ||
| 720 | } | ||
| 610 | } | 721 | } |
| 611 | } | 722 | } |
| 612 | RalewaySemiBold { | 723 | RalewaySemiBold { |
| 613 | id: noPermissionText; | 724 | id: noPermissionText; |
| 614 | visible: !root.canRezCertifiedItems && !root.isWearable; | 725 | visible: !root.canRezCertifiedItems && root.itemType === "entity"; |
| 615 | text: '<font color="' + hifi.colors.redAccent + '"><a href="#">You do not have Certified Rez permissions in this domain.</a></font>' | 726 | text: '<font color="' + hifi.colors.redAccent + '"><a href="#">You do not have Certified Rez permissions in this domain.</a></font>' |
| 616 | // Text size | 727 | // Text size |
| 617 | size: 16; | 728 | size: 16; |
| @@ -640,7 +751,7 @@ Rectangle { · 22 unmodified lines | |||
| 640 | } | 751 | } |
| 641 | RalewaySemiBold { | 752 | RalewaySemiBold { |
| 642 | id: explainRezText; | 753 | id: explainRezText; |
| 643 | visible: !root.isWearable; | 754 | visible: root.itemType === "entity"; |
| 644 | text: '<font color="' + hifi.colors.redAccent + '"><a href="#">What does "Rez" mean?</a></font>' | 755 | text: '<font color="' + hifi.colors.redAccent + '"><a href="#">What does "Rez" mean?</a></font>' |
| 645 | // Text size | 756 | // Text size |
| 646 | size: 16; | 757 | size: 16; |
| @@ -663,9 +774,9 @@ Rectangle { · 16 unmodified lines | |||
| 663 | 774 | ||
| 664 | RalewaySemiBold { | 775 | RalewaySemiBold { |
| 665 | id: myPurchasesLink; | 776 | id: myPurchasesLink; |
| 666 | text: '<font color="' + hifi.colors.blueAccent + '"><a href="#">View this item in My Purchases</a></font>'; | 777 | text: '<font color="' + hifi.colors.primaryHighlight + '"><a href="#">View this item in My Purchases</a></font>'; |
| 667 | // Text size | 778 | // Text size |
| 668 | size: 20; | 779 | size: 18; |
| 669 | // Anchors | 780 | // Anchors |
| 670 | anchors.top: explainRezText.visible ? explainRezText.bottom : (noPermissionText.visible ? noPermissionText.bottom : rezNowButton.bottom); | 781 | anchors.top: explainRezText.visible ? explainRezText.bottom : (noPermissionText.visible ? noPermissionText.bottom : rezNowButton.bottom); |
| 671 | anchors.topMargin: 40; | 782 | anchors.topMargin: 40; |
| @@ -685,12 +796,12 @@ Rectangle { · 13 unmodified lines | |||
| 685 | 796 | ||
| 686 | RalewaySemiBold { | 797 | RalewaySemiBold { |
| 687 | id: walletLink; | 798 | id: walletLink; |
| 688 | text: '<font color="' + hifi.colors.blueAccent + '"><a href="#">View receipt in Wallet</a></font>'; | 799 | text: '<font color="' + hifi.colors.primaryHighlight + '"><a href="#">View receipt in Wallet</a></font>'; |
| 689 | // Text size | 800 | // Text size |
| 690 | size: 20; | 801 | size: 18; |
| 691 | // Anchors | 802 | // Anchors |
| 692 | anchors.top: myPurchasesLink.bottom; | 803 | anchors.top: myPurchasesLink.bottom; |
| 693 | anchors.topMargin: 20; | 804 | anchors.topMargin: 16; |
| 694 | height: paintedHeight; | 805 | height: paintedHeight; |
| 695 | anchors.left: parent.left; | 806 | anchors.left: parent.left; |
| 696 | anchors.right: parent.right; | 807 | anchors.right: parent.right; |
| @@ -708,12 +819,12 @@ Rectangle { · 11 unmodified lines | |||
| 708 | RalewayRegular { | 819 | RalewayRegular { |
| 709 | id: pendingText; | 820 | id: pendingText; |
| 710 | text: 'Your item is marked "pending" while your purchase is being confirmed. ' + | 821 | text: 'Your item is marked "pending" while your purchase is being confirmed. ' + |
| 711 | '<font color="' + hifi.colors.blueAccent + '"><a href="#">Learn More</a></font>'; | 822 | '<b><font color="' + hifi.colors.primaryHighlight + '"><a href="#">Learn More</a></font></b>'; |
| 712 | // Text size | 823 | // Text size |
| 713 | size: 20; | 824 | size: 18; |
| 714 | // Anchors | 825 | // Anchors |
| 715 | anchors.top: walletLink.bottom; | 826 | anchors.top: walletLink.bottom; |
| 716 | anchors.topMargin: 60; | 827 | anchors.topMargin: 32; |
| 717 | height: paintedHeight; | 828 | height: paintedHeight; |
| 718 | anchors.left: parent.left; | 829 | anchors.left: parent.left; |
| 719 | anchors.right: parent.right; | 830 | anchors.right: parent.right; |
| @@ -739,11 +850,10 @@ Rectangle { · 19 unmodified lines | |||
| 739 | color: hifi.buttons.noneBorderlessGray; | 850 | color: hifi.buttons.noneBorderlessGray; |
| 740 | colorScheme: hifi.colorSchemes.light; | 851 | colorScheme: hifi.colorSchemes.light; |
| 741 | anchors.bottom: parent.bottom; | 852 | anchors.bottom: parent.bottom; |
| 742 | anchors.bottomMargin: 20; | 853 | anchors.bottomMargin: 54; |
| 743 | anchors.right: parent.right; | 854 | anchors.right: parent.right; |
| 744 | anchors.rightMargin: 14; | 855 | width: 193; |
| 745 | width: parent.width/2 - anchors.rightMargin; | 856 | height: 44; |
| 746 | height: 60; | ||
| 747 | text: "Continue Shopping"; | 857 | text: "Continue Shopping"; |
| 748 | onClicked: { | 858 | onClicked: { |
| 749 | sendToScript({method: 'checkout_continueShopping', itemId: itemId}); | 859 | sendToScript({method: 'checkout_continueShopping', itemId: itemId}); |
| @@ -851,7 +961,7 @@ Rectangle { · 101 unmodified lines | |||
| 851 | buyButton.color = hifi.buttons.red; | 961 | buyButton.color = hifi.buttons.red; |
| 852 | root.shouldBuyWithControlledFailure = true; | 962 | root.shouldBuyWithControlledFailure = true; |
| 853 | } else { | 963 | } else { |
| 854 | buyButton.text = (itemIsJson ? ((purchasesReceived && balanceReceived) ? (root.alreadyOwned ? "Buy Another" : "Buy"): "--") : "Get Item"); | 964 | buyButton.text = (root.isCertified ? ((ownershipStatusReceived && balanceReceived) ? (root.alreadyOwned ? "Buy Another" : "Buy"): "--") : "Get Item"); |
| 855 | buyButton.color = hifi.buttons.blue; | 965 | buyButton.color = hifi.buttons.blue; |
| 856 | root.shouldBuyWithControlledFailure = false; | 966 | root.shouldBuyWithControlledFailure = false; |
| 857 | } | 967 | } |
| @@ -883,7 +993,7 @@ Rectangle { · 25 unmodified lines | |||
| 883 | itemHref = message.params.itemHref; | 993 | itemHref = message.params.itemHref; |
| 884 | referrer = message.params.referrer; | 994 | referrer = message.params.referrer; |
| 885 | itemAuthor = message.params.itemAuthor; | 995 | itemAuthor = message.params.itemAuthor; |
| 886 | setBuyText(); | 996 | refreshBuyUI(); |
| 887 | break; | 997 | break; |
| 888 | default: | 998 | default: |
| 889 | console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message)); | 999 | console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message)); |
| @@ -891,22 +1001,13 @@ Rectangle { · 1 unmodified line | |||
| 891 | } | 1001 | } |
| 892 | signal sendToScript(var message); | 1002 | signal sendToScript(var message); |
| 893 | 1003 | ||
| 894 | function purchasesContains(purchasesJson, id) { | 1004 | function refreshBuyUI() { |
| 895 | for (var idx = 0; idx < purchasesJson.length; idx++) { | 1005 | if (root.isCertified) { |
| 896 | if(purchasesJson[idx].id === id) { | 1006 | if (root.ownershipStatusReceived && root.balanceReceived) { |
| 897 | return true; | ||
| 898 | } | ||
| 899 | } | ||
| 900 | return false; | ||
| 901 | } | ||
| 902 | |||
| 903 | function setBuyText() { | ||
| 904 | if (root.itemIsJson) { | ||
| 905 | if (root.purchasesReceived && root.balanceReceived) { | ||
| 906 | if (root.balanceAfterPurchase < 0) { | 1007 | if (root.balanceAfterPurchase < 0) { |
| 907 | if (root.alreadyOwned) { | 1008 | if (root.alreadyOwned) { |
| 908 | buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item again.<br>" + | 1009 | buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item again.</b>"; |
| 909 | '<font color="' + hifi.colors.blueAccent + '"><a href="#">View the copy you own in My Purchases</a></font></b>'; | 1010 | viewInMyPurchasesButton.visible = true; |
| 910 | } else { | 1011 | } else { |
| 911 | buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item.</b>"; | 1012 | buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item.</b>"; |
| 912 | } | 1013 | } |
| @@ -916,15 +1017,19 @@ Rectangle { · 3 unmodified lines | |||
| 916 | buyGlyph.size = 54; | 1017 | buyGlyph.size = 54; |
| 917 | } else { | 1018 | } else { |
| 918 | if (root.alreadyOwned) { | 1019 | if (root.alreadyOwned) { |
| 919 | buyText.text = '<b>You already own this item.<br>Purchasing it will buy another copy.<br><font color="' | 1020 | viewInMyPurchasesButton.visible = true; |
| 920 | + hifi.colors.blueAccent + '"><a href="#">View this item in My Purchases</a></font></b>'; | ||
| 921 | buyTextContainer.color = "#FFD6AD"; | ||
| 922 | buyTextContainer.border.color = "#FAC07D"; | ||
| 923 | buyGlyph.text = hifi.glyphs.alert; | ||
| 924 | buyGlyph.size = 46; | ||
| 925 | } else { | 1021 | } else { |
| 926 | buyText.text = ""; | 1022 | buyText.text = ""; |
| 927 | } | 1023 | } |
| 1024 | |||
| 1025 | if (root.itemType === "contentSet" && !Entities.canReplaceContent()) { | ||
| 1026 | buyText.text = "The domain owner must enable 'Replace Content' permissions for you in this " + | ||
| 1027 | "<b>domain's server settings</b> before you can replace this domain's content with <b>" + root.itemName + "</b>"; | ||
| 1028 | buyTextContainer.color = "#FFC3CD"; | ||
| 1029 | buyTextContainer.border.color = "#F3808F"; | ||
| 1030 | buyGlyph.text = hifi.glyphs.alert; | ||
| 1031 | buyGlyph.size = 54; | ||
| 1032 | } | ||
| 928 | } | 1033 | } |
| 929 | } else { | 1034 | } else { |
| 930 | buyText.text = ""; | 1035 | buyText.text = ""; |
| @@ -945,8 +1050,8 @@ Rectangle { · 14 unmodified lines | |||
| 945 | root.activeView = "checkoutSuccess"; | 1050 | root.activeView = "checkoutSuccess"; |
| 946 | } | 1051 | } |
| 947 | root.balanceReceived = false; | 1052 | root.balanceReceived = false; |
| 948 | root.purchasesReceived = false; | 1053 | root.ownershipStatusReceived = false; |
| 949 | Commerce.inventory(); | 1054 | Commerce.alreadyOwned(root.itemId); |
| 950 | Commerce.balance(); | 1055 | Commerce.balance(); |
| 951 | } | 1056 | } |
| 952 | 1057 | ||
| @@ -100,6 +100,10 @@ Rectangle { · 99 unmodified lines | |||
| 100 | size: 20; | 100 | size: 20; |
| 101 | verticalAlignment: Text.AlignTop; | 101 | verticalAlignment: Text.AlignTop; |
| 102 | wrapMode: Text.WordWrap; | 102 | wrapMode: Text.WordWrap; |
| 103 | |||
| 104 | onLinkActivated: { | ||
| 105 | sendToParent({ method: 'commerceLightboxLinkClicked', linkUrl: link }); | ||
| 106 | } | ||
| 103 | } | 107 | } |
| 104 | 108 | ||
| 105 | Item { | 109 | Item { |
| @@ -90,11 +90,11 @@ Rectangle { · 89 unmodified lines | |||
| 90 | id: introText2; | 90 | id: introText2; |
| 91 | text: "My Purchases"; | 91 | text: "My Purchases"; |
| 92 | // Text size | 92 | // Text size |
| 93 | size: 28; | 93 | size: 22; |
| 94 | // Anchors | 94 | // Anchors |
| 95 | anchors.top: introText1.bottom; | 95 | anchors.top: introText1.bottom; |
| 96 | anchors.left: parent.left; | 96 | anchors.left: parent.left; |
| 97 | anchors.leftMargin: 12; | 97 | anchors.leftMargin: 24; |
| 98 | anchors.right: parent.right; | 98 | anchors.right: parent.right; |
| 99 | height: paintedHeight; | 99 | height: paintedHeight; |
| 100 | // Style | 100 | // Style |
| @@ -208,6 +208,7 @@ Rectangle { · 207 unmodified lines | |||
| 208 | // able to click on a button/mouseArea underneath the popup/section. | 208 | // able to click on a button/mouseArea underneath the popup/section. |
| 209 | MouseArea { | 209 | MouseArea { |
| 210 | anchors.fill: parent; | 210 | anchors.fill: parent; |
| 211 | hoverEnabled: true; | ||
| 211 | propagateComposedEvents: false; | 212 | propagateComposedEvents: false; |
| 212 | } | 213 | } |
| 213 | 214 | ||
| @@ -20,6 +20,7 @@ import "../../../styles-uit" · 19 unmodified lines | |||
| 20 | import "../../../controls-uit" as HifiControlsUit | 20 | import "../../../controls-uit" as HifiControlsUit |
| 21 | import "../../../controls" as HifiControls | 21 | import "../../../controls" as HifiControls |
| 22 | import "../wallet" as HifiWallet | 22 | import "../wallet" as HifiWallet |
| 23 | import TabletScriptingInterface 1.0 | ||
| 23 | 24 | ||
| 24 | // references XXX from root context | 25 | // references XXX from root context |
| 25 | 26 | ||
| @@ -29,7 +30,6 @@ Item { · 3 unmodified lines | |||
| 29 | id: root; | 30 | id: root; |
| 30 | property string purchaseStatus; | 31 | property string purchaseStatus; |
| 31 | property bool purchaseStatusChanged; | 32 | property bool purchaseStatusChanged; |
| 32 | property bool canRezCertifiedItems: false; | ||
| 33 | property string itemName; | 33 | property string itemName; |
| 34 | property string itemId; | 34 | property string itemId; |
| 35 | property string itemPreviewImageUrl; | 35 | property string itemPreviewImageUrl; |
| @@ -39,7 +39,14 @@ Item { · 3 unmodified lines | |||
| 39 | property int itemEdition; | 39 | property int itemEdition; |
| 40 | property int numberSold; | 40 | property int numberSold; |
| 41 | property int limitedRun; | 41 | property int limitedRun; |
| 42 | property bool isWearable; | 42 | property string itemType; |
| 43 | property var itemTypesArray: ["entity", "wearable", "contentSet", "app", "avatar"]; | ||
| 44 | property var buttonTextNormal: ["REZ", "WEAR", "REPLACE", "INSTALL", "WEAR"]; | ||
| 45 | property var buttonTextClicked: ["REZZED", "WORN", "REPLACED", "INSTALLED", "WORN"] | ||
| 46 | property var buttonGlyph: [hifi.glyphs.wand, hifi.glyphs.hat, hifi.glyphs.globe, hifi.glyphs.install, hifi.glyphs.avatar]; | ||
| 47 | property bool showConfirmation: false; | ||
| 48 | property bool hasPermissionToRezThis; | ||
| 49 | property bool permissionExplanationCardVisible; | ||
| 43 | 50 | ||
| 44 | property string originalStatusText; | 51 | property string originalStatusText; |
| 45 | property string originalStatusColor; | 52 | property string originalStatusColor; |
| @@ -47,6 +54,35 @@ Item { · 1 unmodified line | |||
| 47 | height: 110; | 54 | height: 110; |
| 48 | width: parent.width; | 55 | width: parent.width; |
| 49 | 56 | ||
| 57 | Connections { | ||
| 58 | target: Commerce; | ||
| 59 | |||
| 60 | onContentSetChanged: { | ||
| 61 | if (contentSetHref === root.itemHref) { | ||
| 62 | showConfirmation = true; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | Connections { | ||
| 68 | target: MyAvatar; | ||
| 69 | |||
| 70 | onSkeletonModelURLChanged: { | ||
| 71 | if (skeletonModelURL === root.itemHref) { | ||
| 72 | showConfirmation = true; | ||
| 73 | } | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | onItemTypeChanged: { | ||
| 78 | if ((itemType === "entity" && (!Entities.canRezCertified() && !Entities.canRezTmpCertified())) || | ||
| 79 | (itemType === "contentSet" && !Entities.canReplaceContent())) { | ||
| 80 | root.hasPermissionToRezThis = false; | ||
| 81 | } else { | ||
| 82 | root.hasPermissionToRezThis = true; | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 50 | onPurchaseStatusChangedChanged: { | 86 | onPurchaseStatusChangedChanged: { |
| 51 | if (root.purchaseStatusChanged === true && root.purchaseStatus === "confirmed") { | 87 | if (root.purchaseStatusChanged === true && root.purchaseStatus === "confirmed") { |
| 52 | root.originalStatusText = statusText.text; | 88 | root.originalStatusText = statusText.text; |
| @@ -57,6 +93,15 @@ Item { · 4 unmodified lines | |||
| 57 | } | 93 | } |
| 58 | } | 94 | } |
| 59 | 95 | ||
| 96 | onShowConfirmationChanged: { | ||
| 97 | if (root.showConfirmation) { | ||
| 98 | rezzedNotifContainer.visible = true; | ||
| 99 | rezzedNotifContainerTimer.start(); | ||
| 100 | UserActivityLogger.commerceEntityRezzed(root.itemId, "purchases", root.itemType); | ||
| 101 | root.showConfirmation = false; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 60 | Timer { | 105 | Timer { |
| 61 | id: confirmedTimer; | 106 | id: confirmedTimer; |
| 62 | interval: 3000; | 107 | interval: 3000; |
| @@ -73,10 +118,10 @@ Item { · 10 unmodified lines | |||
| 73 | color: hifi.colors.white; | 118 | color: hifi.colors.white; |
| 74 | // Size | 119 | // Size |
| 75 | anchors.left: parent.left; | 120 | anchors.left: parent.left; |
| 76 | anchors.leftMargin: 8; | 121 | anchors.leftMargin: 16; |
| 77 | anchors.right: parent.right; | 122 | anchors.right: parent.right; |
| 78 | anchors.rightMargin: 8; | 123 | anchors.rightMargin: 16; |
| 79 | anchors.top: parent.top; | 124 | anchors.verticalCenter: parent.verticalCenter; |
| 80 | height: root.height - 10; | 125 | height: root.height - 10; |
| 81 | 126 | ||
| 82 | Image { | 127 | Image { |
| @@ -96,15 +141,20 @@ Item { · 13 unmodified lines | |||
| 96 | } | 141 | } |
| 97 | } | 142 | } |
| 98 | 143 | ||
| 99 | 144 | TextMetrics { | |
| 145 | id: itemNameTextMetrics; | ||
| 146 | font: itemName.font; | ||
| 147 | text: itemName.text; | ||
| 148 | } | ||
| 100 | RalewaySemiBold { | 149 | RalewaySemiBold { |
| 101 | id: itemName; | 150 | id: itemName; |
| 102 | anchors.top: itemPreviewImage.top; | 151 | anchors.top: itemPreviewImage.top; |
| 103 | anchors.topMargin: 4; | 152 | anchors.topMargin: 4; |
| 104 | anchors.left: itemPreviewImage.right; | 153 | anchors.left: itemPreviewImage.right; |
| 105 | anchors.leftMargin: 8; | 154 | anchors.leftMargin: 8; |
| 106 | anchors.right: buttonContainer.left; | 155 | width: !noPermissionGlyph.visible ? (buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin) : |
| 107 | anchors.rightMargin: 8; | 156 | Math.min(itemNameTextMetrics.tightBoundingRect.width + 2, |
| 157 | buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin - noPermissionGlyph.width + 2); | ||
| 108 | height: paintedHeight; | 158 | height: paintedHeight; |
| 109 | // Text size | 159 | // Text size |
| 110 | size: 24; | 160 | size: 24; |
| @@ -130,6 +180,93 @@ Item { · 19 unmodified lines | |||
| 130 | } | 180 | } |
| 131 | } | 181 | } |
| 132 | } | 182 | } |
| 183 | HiFiGlyphs { | ||
| 184 | id: noPermissionGlyph; | ||
| 185 | visible: !root.hasPermissionToRezThis; | ||
| 186 | anchors.verticalCenter: itemName.verticalCenter; | ||
| 187 | anchors.left: itemName.right; | ||
| 188 | anchors.leftMargin: itemName.truncated ? -10 : -2; | ||
| 189 | text: hifi.glyphs.info; | ||
| 190 | // Size | ||
| 191 | size: 40; | ||
| 192 | width: 32; | ||
| 193 | // Style | ||
| 194 | color: hifi.colors.redAccent; | ||
| 195 | |||
| 196 | MouseArea { | ||
| 197 | anchors.fill: parent; | ||
| 198 | hoverEnabled: true; | ||
| 199 | |||
| 200 | onEntered: { | ||
| 201 | noPermissionGlyph.color = hifi.colors.redHighlight; | ||
| 202 | } | ||
| 203 | onExited: { | ||
| 204 | noPermissionGlyph.color = hifi.colors.redAccent; | ||
| 205 | } | ||
| 206 | onClicked: { | ||
| 207 | root.sendToPurchases({ method: 'openPermissionExplanationCard' }); | ||
| 208 | } | ||
| 209 | } | ||
| 210 | } | ||
| 211 | Rectangle { | ||
| 212 | id: permissionExplanationCard; | ||
| 213 | z: 995; | ||
| 214 | visible: root.permissionExplanationCardVisible; | ||
| 215 | anchors.fill: parent; | ||
| 216 | color: hifi.colors.white; | ||
| 217 | |||
| 218 | RalewayRegular { | ||
| 219 | id: permissionExplanationText; | ||
| 220 | text: { | ||
| 221 | if (root.itemType === "contentSet") { | ||
| 222 | "You do not have 'Replace Content' permissions in this domain. <a href='#replaceContentPermission'>Learn more</a>"; | ||
| 223 | } else if (root.itemType === "entity") { | ||
| 224 | "You do not have 'Rez Certified' permissions in this domain. <a href='#rezCertifiedPermission'>Learn more</a>"; | ||
| 225 | } else { | ||
| 226 | "" | ||
| 227 | } | ||
| 228 | } | ||
| 229 | size: 16; | ||
| 230 | anchors.left: parent.left; | ||
| 231 | anchors.leftMargin: 30; | ||
| 232 | anchors.top: parent.top; | ||
| 233 | anchors.bottom: parent.bottom; | ||
| 234 | anchors.right: permissionExplanationGlyph.left; | ||
| 235 | color: hifi.colors.baseGray; | ||
| 236 | wrapMode: Text.WordWrap; | ||
| 237 | verticalAlignment: Text.AlignVCenter; | ||
| 238 | |||
| 239 | onLinkActivated: { | ||
| 240 | sendToPurchases({method: 'showPermissionsExplanation', itemType: root.itemType}); | ||
| 241 | } | ||
| 242 | } | ||
| 243 | // "Close" button | ||
| 244 | HiFiGlyphs { | ||
| 245 | id: permissionExplanationGlyph; | ||
| 246 | text: hifi.glyphs.close; | ||
| 247 | color: hifi.colors.baseGray; | ||
| 248 | size: 26; | ||
| 249 | anchors.top: parent.top; | ||
| 250 | anchors.bottom: parent.bottom; | ||
| 251 | anchors.right: parent.right; | ||
| 252 | width: 77; | ||
| 253 | horizontalAlignment: Text.AlignHCenter; | ||
| 254 | verticalAlignment: Text.AlignVCenter; | ||
| 255 | MouseArea { | ||
| 256 | anchors.fill: parent; | ||
| 257 | hoverEnabled: true; | ||
| 258 | onEntered: { | ||
| 259 | parent.text = hifi.glyphs.closeInverted; | ||
| 260 | } | ||
| 261 | onExited: { | ||
| 262 | parent.text = hifi.glyphs.close; | ||
| 263 | } | ||
| 264 | onClicked: { | ||
| 265 | root.sendToPurchases({ method: 'openPermissionExplanationCard', closeAll: true }); | ||
| 266 | } | ||
| 267 | } | ||
| 268 | } | ||
| 269 | } | ||
| 133 | 270 | ||
| 134 | Item { | 271 | Item { |
| 135 | id: certificateContainer; | 272 | id: certificateContainer; |
| @@ -151,19 +288,19 @@ Item { · 15 unmodified lines | |||
| 151 | anchors.bottom: parent.bottom; | 288 | anchors.bottom: parent.bottom; |
| 152 | width: 32; | 289 | width: 32; |
| 153 | // Style | 290 | // Style |
| 154 | color: hifi.colors.lightGray; | 291 | color: hifi.colors.black; |
| 155 | } | 292 | } |
| 156 | 293 | ||
| 157 | RalewayRegular { | 294 | RalewayRegular { |
| 158 | id: viewCertificateText; | 295 | id: viewCertificateText; |
| 159 | text: "VIEW CERTIFICATE"; | 296 | text: "VIEW CERTIFICATE"; |
| 160 | size: 14; | 297 | size: 13; |
| 161 | anchors.left: certificateIcon.right; | 298 | anchors.left: certificateIcon.right; |
| 162 | anchors.leftMargin: 4; | 299 | anchors.leftMargin: 4; |
| 163 | anchors.top: parent.top; | 300 | anchors.top: parent.top; |
| 164 | anchors.bottom: parent.bottom; | 301 | anchors.bottom: parent.bottom; |
| 165 | anchors.right: parent.right; | 302 | anchors.right: parent.right; |
| 166 | color: hifi.colors.lightGray; | 303 | color: hifi.colors.black; |
| 167 | } | 304 | } |
| 168 | 305 | ||
| 169 | MouseArea { | 306 | MouseArea { |
| @@ -173,13 +310,13 @@ Item { · 3 unmodified lines | |||
| 173 | sendToPurchases({method: 'purchases_itemCertificateClicked', itemCertificateId: root.certificateId}); | 310 | sendToPurchases({method: 'purchases_itemCertificateClicked', itemCertificateId: root.certificateId}); |
| 174 | } | 311 | } |
| 175 | onEntered: { | 312 | onEntered: { |
| 176 | certificateIcon.color = hifi.colors.black; | ||
| 177 | viewCertificateText.color = hifi.colors.black; | ||
| 178 | } | ||
| 179 | onExited: { | ||
| 180 | certificateIcon.color = hifi.colors.lightGray; | 313 | certificateIcon.color = hifi.colors.lightGray; |
| 181 | viewCertificateText.color = hifi.colors.lightGray; | 314 | viewCertificateText.color = hifi.colors.lightGray; |
| 182 | } | 315 | } |
| 316 | onExited: { | ||
| 317 | certificateIcon.color = hifi.colors.black; | ||
| 318 | viewCertificateText.color = hifi.colors.black; | ||
| 319 | } | ||
| 183 | } | 320 | } |
| 184 | } | 321 | } |
| 185 | 322 | ||
| @@ -193,14 +330,14 @@ Item { · 7 unmodified lines | |||
| 193 | anchors.right: buttonContainer.left; | 330 | anchors.right: buttonContainer.left; |
| 194 | anchors.rightMargin: 2; | 331 | anchors.rightMargin: 2; |
| 195 | 332 | ||
| 196 | FiraSansRegular { | 333 | RalewayRegular { |
| 197 | anchors.left: parent.left; | 334 | anchors.left: parent.left; |
| 198 | anchors.top: parent.top; | 335 | anchors.top: parent.top; |
| 199 | anchors.bottom: parent.bottom; | 336 | anchors.bottom: parent.bottom; |
| 200 | width: paintedWidth; | 337 | width: paintedWidth; |
| 201 | text: "#" + root.itemEdition; | 338 | text: "#" + root.itemEdition; |
| 202 | size: 15; | 339 | size: 13; |
| 203 | color: "#cc6a6a6a"; | 340 | color: hifi.colors.black; |
| 204 | verticalAlignment: Text.AlignTop; | 341 | verticalAlignment: Text.AlignTop; |
| 205 | } | 342 | } |
| 206 | } | 343 | } |
| @@ -311,7 +448,7 @@ Item { · 104 unmodified lines | |||
| 311 | id: rezzedNotifContainer; | 448 | id: rezzedNotifContainer; |
| 312 | z: 998; | 449 | z: 998; |
| 313 | visible: false; | 450 | visible: false; |
| 314 | color: hifi.colors.blueHighlight; | 451 | color: "#1FC6A6"; |
| 315 | anchors.fill: buttonContainer; | 452 | anchors.fill: buttonContainer; |
| 316 | MouseArea { | 453 | MouseArea { |
| 317 | anchors.fill: parent; | 454 | anchors.fill: parent; |
| @@ -321,8 +458,8 @@ Item { · 3 unmodified lines | |||
| 321 | 458 | ||
| 322 | RalewayBold { | 459 | RalewayBold { |
| 323 | anchors.fill: parent; | 460 | anchors.fill: parent; |
| 324 | text: "REZZED"; | 461 | text: (root.buttonTextClicked)[itemTypesArray.indexOf(root.itemType)]; |
| 325 | size: 18; | 462 | size: 15; |
| 326 | color: hifi.colors.white; | 463 | color: hifi.colors.white; |
| 327 | verticalAlignment: Text.AlignVCenter; | 464 | verticalAlignment: Text.AlignVCenter; |
| 328 | horizontalAlignment: Text.AlignHCenter; | 465 | horizontalAlignment: Text.AlignHCenter; |
| @@ -337,25 +474,47 @@ Item { · 8 unmodified lines | |||
| 337 | 474 | ||
| 338 | Button { | 475 | Button { |
| 339 | id: buttonContainer; | 476 | id: buttonContainer; |
| 340 | property int color: hifi.buttons.red; | 477 | property int color: hifi.buttons.blue; |
| 341 | property int colorScheme: hifi.colorSchemes.light; | 478 | property int colorScheme: hifi.colorSchemes.light; |
| 342 | 479 | ||
| 343 | anchors.top: parent.top; | 480 | anchors.top: parent.top; |
| 481 | anchors.topMargin: 4; | ||
| 344 | anchors.bottom: parent.bottom; | 482 | anchors.bottom: parent.bottom; |
| 483 | anchors.bottomMargin: 4; | ||
| 345 | anchors.right: parent.right; | 484 | anchors.right: parent.right; |
| 485 | anchors.rightMargin: 4; | ||
| 346 | width: height; | 486 | width: height; |
| 347 | enabled: (root.canRezCertifiedItems || root.isWearable) && root.purchaseStatus !== "invalidated"; | 487 | enabled: root.hasPermissionToRezThis && |
| 488 | root.purchaseStatus !== "invalidated" && | ||
| 489 | MyAvatar.skeletonModelURL !== root.itemHref; | ||
| 490 | |||
| 491 | onHoveredChanged: { | ||
| 492 | if (hovered) { | ||
| 493 | Tablet.playSound(TabletEnums.ButtonHover); | ||
| 494 | } | ||
| 495 | } | ||
| 496 | |||
| 497 | onFocusChanged: { | ||
| 498 | if (focus) { | ||
| 499 | Tablet.playSound(TabletEnums.ButtonHover); | ||
| 500 | } | ||
| 501 | } | ||
| 348 | 502 | ||
| 349 | onClicked: { | 503 | onClicked: { |
| 350 | sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable}); | 504 | Tablet.playSound(TabletEnums.ButtonClick); |
| 351 | rezzedNotifContainer.visible = true; | 505 | if (root.itemType === "contentSet") { |
| 352 | rezzedNotifContainerTimer.start(); | 506 | sendToPurchases({method: 'showReplaceContentLightbox', itemHref: root.itemHref}); |
| 353 | UserActivityLogger.commerceEntityRezzed(root.itemId, "purchases", root.isWearable ? "rez" : "wear"); | 507 | } else if (root.itemType === "avatar") { |
| 508 | sendToPurchases({method: 'showChangeAvatarLightbox', itemName: root.itemName, itemHref: root.itemHref}); | ||
| 509 | } else { | ||
| 510 | sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); | ||
| 511 | root.showConfirmation = true; | ||
| 512 | } | ||
| 354 | } | 513 | } |
| 355 | 514 | ||
| 356 | style: ButtonStyle { | 515 | style: ButtonStyle { |
| 357 | |||
| 358 | background: Rectangle { | 516 | background: Rectangle { |
| 517 | radius: 4; | ||
| 359 | gradient: Gradient { | 518 | gradient: Gradient { |
| 360 | GradientStop { | 519 | GradientStop { |
| 361 | position: 0.2 | 520 | position: 0.2 |
| @@ -390,13 +549,13 @@ Item { · 28 unmodified lines | |||
| 390 | 549 | ||
| 391 | label: Item { | 550 | label: Item { |
| 392 | HiFiGlyphs { | 551 | HiFiGlyphs { |
| 393 | id: lightningIcon; | 552 | id: rezIcon; |
| 394 | text: hifi.glyphs.lightning; | 553 | text: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)]; |
| 395 | // Size | 554 | // Size |
| 396 | size: 32; | 555 | size: 60; |
| 397 | // Anchors | 556 | // Anchors |
| 398 | anchors.top: parent.top; | 557 | anchors.top: parent.top; |
| 399 | anchors.topMargin: 12; | 558 | anchors.topMargin: 0; |
| 400 | anchors.left: parent.left; | 559 | anchors.left: parent.left; |
| 401 | anchors.right: parent.right; | 560 | anchors.right: parent.right; |
| 402 | horizontalAlignment: Text.AlignHCenter; | 561 | horizontalAlignment: Text.AlignHCenter; |
| @@ -405,18 +564,19 @@ Item { · 2 unmodified lines | |||
| 405 | : hifi.buttons.disabledTextColor[control.colorScheme] | 564 | : hifi.buttons.disabledTextColor[control.colorScheme] |
| 406 | } | 565 | } |
| 407 | RalewayBold { | 566 | RalewayBold { |
| 408 | anchors.top: lightningIcon.bottom; | 567 | id: rezIconLabel; |
| 409 | anchors.topMargin: -20; | 568 | anchors.top: rezIcon.bottom; |
| 569 | anchors.topMargin: -4; | ||
| 410 | anchors.right: parent.right; | 570 | anchors.right: parent.right; |
| 411 | anchors.left: parent.left; | 571 | anchors.left: parent.left; |
| 412 | anchors.bottom: parent.bottom; | 572 | anchors.bottom: parent.bottom; |
| 413 | font.capitalization: Font.AllUppercase | 573 | font.capitalization: Font.AllUppercase |
| 414 | color: enabled ? hifi.buttons.textColor[control.color] | 574 | color: enabled ? hifi.buttons.textColor[control.color] |
| 415 | : hifi.buttons.disabledTextColor[control.colorScheme] | 575 | : hifi.buttons.disabledTextColor[control.colorScheme] |
| 416 | size: 16; | 576 | size: 15; |
| 417 | verticalAlignment: Text.AlignVCenter | 577 | verticalAlignment: Text.AlignVCenter |
| 418 | horizontalAlignment: Text.AlignHCenter | 578 | horizontalAlignment: Text.AlignHCenter |
| 419 | text: root.isWearable ? "Wear It" : "Rez It" | 579 | text: MyAvatar.skeletonModelURL === root.itemHref ? "CURRENT" : (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)]; |
| 420 | } | 580 | } |
| 421 | } | 581 | } |
| 422 | } | 582 | } |
| @@ -425,11 +585,11 @@ Item { · 2 unmodified lines | |||
| 425 | 585 | ||
| 426 | DropShadow { | 586 | DropShadow { |
| 427 | anchors.fill: mainContainer; | 587 | anchors.fill: mainContainer; |
| 428 | horizontalOffset: 3; | 588 | horizontalOffset: 0; |
| 429 | verticalOffset: 3; | 589 | verticalOffset: 4; |
| 430 | radius: 8.0; | 590 | radius: 4.0; |
| 431 | samples: 17; | 591 | samples: 9 |
| 432 | color: "#80000000"; | 592 | color: Qt.rgba(0, 0, 0, 0.25); |
| 433 | source: mainContainer; | 593 | source: mainContainer; |
| 434 | } | 594 | } |
| 435 | 595 | ||
| @@ -32,7 +32,6 @@ Rectangle { · 31 unmodified lines | |||
| 32 | property bool securityImageResultReceived: false; | 32 | property bool securityImageResultReceived: false; |
| 33 | property bool purchasesReceived: false; | 33 | property bool purchasesReceived: false; |
| 34 | property bool punctuationMode: false; | 34 | property bool punctuationMode: false; |
| 35 | property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified(); | ||
| 36 | property bool pendingInventoryReply: true; | 35 | property bool pendingInventoryReply: true; |
| 37 | property bool isShowingMyItems: false; | 36 | property bool isShowingMyItems: false; |
| 38 | property bool isDebuggingFirstUseTutorial: false; | 37 | property bool isDebuggingFirstUseTutorial: false; |
| @@ -148,7 +147,11 @@ Rectangle { · 109 unmodified lines | |||
| 148 | 147 | ||
| 149 | Connections { | 148 | Connections { |
| 150 | onSendToParent: { | 149 | onSendToParent: { |
| 151 | sendToScript(msg); | 150 | if (msg.method === 'commerceLightboxLinkClicked') { |
| 151 | Qt.openUrlExternally(msg.linkUrl); | ||
| 152 | } else { | ||
| 153 | sendToScript(msg); | ||
| 154 | } | ||
| 152 | } | 155 | } |
| 153 | } | 156 | } |
| 154 | } | 157 | } |
| @@ -297,7 +300,7 @@ Rectangle { · 142 unmodified lines | |||
| 297 | anchors.left: parent.left; | 300 | anchors.left: parent.left; |
| 298 | anchors.leftMargin: 8; | 301 | anchors.leftMargin: 8; |
| 299 | anchors.right: parent.right; | 302 | anchors.right: parent.right; |
| 300 | anchors.rightMargin: 12; | 303 | anchors.rightMargin: 16; |
| 301 | anchors.top: parent.top; | 304 | anchors.top: parent.top; |
| 302 | anchors.topMargin: 4; | 305 | anchors.topMargin: 4; |
| 303 | 306 | ||
| @@ -308,11 +311,11 @@ Rectangle { · 4 unmodified lines | |||
| 308 | anchors.bottom: parent.bottom; | 311 | anchors.bottom: parent.bottom; |
| 309 | anchors.bottomMargin: 10; | 312 | anchors.bottomMargin: 10; |
| 310 | anchors.left: parent.left; | 313 | anchors.left: parent.left; |
| 311 | anchors.leftMargin: 4; | 314 | anchors.leftMargin: 16; |
| 312 | width: paintedWidth; | 315 | width: paintedWidth; |
| 313 | text: isShowingMyItems ? "My Items" : "My Purchases"; | 316 | text: isShowingMyItems ? "My Items" : "My Purchases"; |
| 314 | color: hifi.colors.baseGray; | 317 | color: hifi.colors.black; |
| 315 | size: 28; | 318 | size: 22; |
| 316 | } | 319 | } |
| 317 | 320 | ||
| 318 | HifiControlsUit.TextField { | 321 | HifiControlsUit.TextField { |
| @@ -323,8 +326,8 @@ Rectangle { · 4 unmodified lines | |||
| 323 | hasRoundedBorder: true; | 326 | hasRoundedBorder: true; |
| 324 | anchors.left: myText.right; | 327 | anchors.left: myText.right; |
| 325 | anchors.leftMargin: 16; | 328 | anchors.leftMargin: 16; |
| 326 | anchors.top: parent.top; | 329 | height: 39; |
| 327 | anchors.bottom: parent.bottom; | 330 | anchors.verticalCenter: parent.verticalCenter; |
| 328 | anchors.right: parent.right; | 331 | anchors.right: parent.right; |
| 329 | placeholderText: "filter items"; | 332 | placeholderText: "filter items"; |
| 330 | 333 | ||
| @@ -345,7 +348,7 @@ Rectangle { · 14 unmodified lines | |||
| 345 | 348 | ||
| 346 | HifiControlsUit.Separator { | 349 | HifiControlsUit.Separator { |
| 347 | id: separator; | 350 | id: separator; |
| 348 | colorScheme: 1; | 351 | colorScheme: 2; |
| 349 | anchors.left: parent.left; | 352 | anchors.left: parent.left; |
| 350 | anchors.right: parent.right; | 353 | anchors.right: parent.right; |
| 351 | anchors.top: filterBarContainer.bottom; | 354 | anchors.top: filterBarContainer.bottom; |
| @@ -365,69 +368,6 @@ Rectangle { · 13 unmodified lines | |||
| 365 | id: filteredPurchasesModel; | 368 | id: filteredPurchasesModel; |
| 366 | } | 369 | } |
| 367 | 370 | ||
| 368 | Rectangle { | ||
| 369 | id: cantRezCertified; | ||
| 370 | visible: !root.canRezCertifiedItems; | ||
| 371 | color: "#FFC3CD"; | ||
| 372 | radius: 4; | ||
| 373 | border.color: hifi.colors.redAccent; | ||
| 374 | border.width: 1; | ||
| 375 | anchors.top: separator.bottom; | ||
| 376 | anchors.topMargin: 12; | ||
| 377 | anchors.left: parent.left; | ||
| 378 | anchors.leftMargin: 16; | ||
| 379 | anchors.right: parent.right; | ||
| 380 | anchors.rightMargin: 16; | ||
| 381 | height: 80; | ||
| 382 | |||
| 383 | HiFiGlyphs { | ||
| 384 | id: lightningIcon; | ||
| 385 | text: hifi.glyphs.lightning; | ||
| 386 | // Size | ||
| 387 | size: 36; | ||
| 388 | // Anchors | ||
| 389 | anchors.top: parent.top; | ||
| 390 | anchors.topMargin: 18; | ||
| 391 | anchors.left: parent.left; | ||
| 392 | anchors.leftMargin: 12; | ||
| 393 | horizontalAlignment: Text.AlignHCenter; | ||
| 394 | // Style | ||
| 395 | color: hifi.colors.lightGray; | ||
| 396 | } | ||
| 397 | |||
| 398 | RalewayRegular { | ||
| 399 | text: "You don't have permission to rez certified items in this domain. " + | ||
| 400 | '<b><font color="' + hifi.colors.blueAccent + '"><a href="#">Learn More</a></font></b>'; | ||
| 401 | // Text size | ||
| 402 | size: 18; | ||
| 403 | // Anchors | ||
| 404 | anchors.top: parent.top; | ||
| 405 | anchors.topMargin: 4; | ||
| 406 | anchors.left: lightningIcon.right; | ||
| 407 | anchors.leftMargin: 8; | ||
| 408 | anchors.right: parent.right; | ||
| 409 | anchors.rightMargin: 8; | ||
| 410 | anchors.bottom: parent.bottom; | ||
| 411 | anchors.bottomMargin: 4; | ||
| 412 | // Style | ||
| 413 | color: hifi.colors.baseGray; | ||
| 414 | wrapMode: Text.WordWrap; | ||
| 415 | // Alignment | ||
| 416 | verticalAlignment: Text.AlignVCenter; | ||
| 417 | |||
| 418 | onLinkActivated: { | ||
| 419 | lightboxPopup.titleText = "Rez Permission Required"; | ||
| 420 | lightboxPopup.bodyText = "You don't have permission to rez certified items in this domain.<br><br>" + | ||
| 421 | "Use the <b>GOTO app</b> to visit another domain or <b>go to your own sandbox.</b>"; | ||
| 422 | lightboxPopup.button1text = "CLOSE"; | ||
| 423 | lightboxPopup.button1method = "root.visible = false;" | ||
| 424 | lightboxPopup.button2text = "OPEN GOTO"; | ||
| 425 | lightboxPopup.button2method = "sendToParent({method: 'purchases_openGoTo'});"; | ||
| 426 | lightboxPopup.visible = true; | ||
| 427 | } | ||
| 428 | } | ||
| 429 | } | ||
| 430 | |||
| 431 | ListView { | 371 | ListView { |
| 432 | id: purchasesContentsList; | 372 | id: purchasesContentsList; |
| 433 | visible: (root.isShowingMyItems && filteredPurchasesModel.count !== 0) || (!root.isShowingMyItems && filteredPurchasesModel.count !== 0); | 373 | visible: (root.isShowingMyItems && filteredPurchasesModel.count !== 0) || (!root.isShowingMyItems && filteredPurchasesModel.count !== 0); |
| @@ -436,13 +376,12 @@ Rectangle { · 2 unmodified lines | |||
| 436 | snapMode: ListView.SnapToItem; | 376 | snapMode: ListView.SnapToItem; |
| 437 | highlightRangeMode: ListView.StrictlyEnforceRange; | 377 | highlightRangeMode: ListView.StrictlyEnforceRange; |
| 438 | // Anchors | 378 | // Anchors |
| 439 | anchors.top: root.canRezCertifiedItems ? separator.bottom : cantRezCertified.bottom; | 379 | anchors.top: separator.bottom; |
| 440 | anchors.topMargin: 12; | 380 | anchors.topMargin: 12; |
| 441 | anchors.left: parent.left; | 381 | anchors.left: parent.left; |
| 442 | anchors.bottom: parent.bottom; | 382 | anchors.bottom: parent.bottom; |
| 443 | width: parent.width; | 383 | width: parent.width; |
| 444 | delegate: PurchasedItem { | 384 | delegate: PurchasedItem { |
| 445 | canRezCertifiedItems: root.canRezCertifiedItems; | ||
| 446 | itemName: title; | 385 | itemName: title; |
| 447 | itemId: id; | 386 | itemId: id; |
| 448 | itemPreviewImageUrl: preview; | 387 | itemPreviewImageUrl: preview; |
| @@ -454,16 +393,31 @@ Rectangle { · 5 unmodified lines | |||
| 454 | numberSold: model.number_sold; | 393 | numberSold: model.number_sold; |
| 455 | limitedRun: model.limited_run; | 394 | limitedRun: model.limited_run; |
| 456 | displayedItemCount: model.displayedItemCount; | 395 | displayedItemCount: model.displayedItemCount; |
| 457 | isWearable: model.categories.indexOf("Wearables") > -1; | 396 | permissionExplanationCardVisible: model.permissionExplanationCardVisible; |
| 458 | anchors.topMargin: 12; | 397 | itemType: { |
| 459 | anchors.bottomMargin: 12; | 398 | if (model.root_file_url.indexOf(".fst") > -1) { |
| 399 | "avatar"; | ||
| 400 | } else if (model.categories.indexOf("Wearables") > -1) { | ||
| 401 | "wearable"; | ||
| 402 | } else if (model.root_file_url.endsWith('.json.gz')) { | ||
| 403 | "contentSet"; | ||
| 404 | } else if (model.root_file_url.endsWith('.app.json')) { | ||
| 405 | "app"; | ||
| 406 | } else if (model.root_file_url.endsWith('.json')) { | ||
| 407 | "entity"; | ||
| 408 | } else { | ||
| 409 | "unknown"; | ||
| 410 | } | ||
| 411 | } | ||
| 412 | anchors.topMargin: 10; | ||
| 413 | anchors.bottomMargin: 10; | ||
| 460 | 414 | ||
| 461 | Connections { | 415 | Connections { |
| 462 | onSendToPurchases: { | 416 | onSendToPurchases: { |
| 463 | if (msg.method === 'purchases_itemInfoClicked') { | 417 | if (msg.method === 'purchases_itemInfoClicked') { |
| 464 | sendToScript({method: 'purchases_itemInfoClicked', itemId: itemId}); | 418 | sendToScript({method: 'purchases_itemInfoClicked', itemId: itemId}); |
| 465 | } else if (msg.method === "purchases_rezClicked") { | 419 | } else if (msg.method === "purchases_rezClicked") { |
| 466 | sendToScript({method: 'purchases_rezClicked', itemHref: itemHref, isWearable: isWearable}); | 420 | sendToScript({method: 'purchases_rezClicked', itemHref: itemHref, itemType: itemType}); |
| 467 | } else if (msg.method === 'purchases_itemCertificateClicked') { | 421 | } else if (msg.method === 'purchases_itemCertificateClicked') { |
| 468 | inspectionCertificate.visible = true; | 422 | inspectionCertificate.visible = true; |
| 469 | inspectionCertificate.isLightbox = true; | 423 | inspectionCertificate.isLightbox = true; |
| @@ -482,8 +436,51 @@ Rectangle { · 12 unmodified lines | |||
| 482 | lightboxPopup.button1text = "CLOSE"; | 436 | lightboxPopup.button1text = "CLOSE"; |
| 483 | lightboxPopup.button1method = "root.visible = false;" | 437 | lightboxPopup.button1method = "root.visible = false;" |
| 484 | lightboxPopup.visible = true; | 438 | lightboxPopup.visible = true; |
| 439 | } else if (msg.method === "showReplaceContentLightbox") { | ||
| 440 | lightboxPopup.titleText = "Replace Content"; | ||
| 441 | lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain. " + | ||
| 442 | "If you want to save the state of the content in this domain, create a backup before proceeding.<br><br>" + | ||
| 443 | "For more information about backing up and restoring content, " + | ||
| 444 | "<a href='https://docs.highfidelity.com/create-and-explore/start-working-in-your-sandbox/restoring-sandbox-content'>" + | ||
| 445 | "click here to open info on your desktop browser."; | ||
| 446 | lightboxPopup.button1text = "CANCEL"; | ||
| 447 | lightboxPopup.button1method = "root.visible = false;" | ||
| 448 | lightboxPopup.button2text = "CONFIRM"; | ||
| 449 | lightboxPopup.button2method = "Commerce.replaceContentSet('" + msg.itemHref + "'); root.visible = false;"; | ||
| 450 | lightboxPopup.visible = true; | ||
| 451 | } else if (msg.method === "showChangeAvatarLightbox") { | ||
| 452 | lightboxPopup.titleText = "Change Avatar"; | ||
| 453 | lightboxPopup.bodyText = "This will change your current avatar to " + msg.itemName + " while retaining your wearables."; | ||
| 454 | lightboxPopup.button1text = "CANCEL"; | ||
| 455 | lightboxPopup.button1method = "root.visible = false;" | ||
| 456 | lightboxPopup.button2text = "CONFIRM"; | ||
| 457 | lightboxPopup.button2method = "MyAvatar.useFullAvatarURL('" + msg.itemHref + "'); root.visible = false;"; | ||
| 458 | lightboxPopup.visible = true; | ||
| 459 | } else if (msg.method === "showPermissionsExplanation") { | ||
| 460 | if (msg.itemType === "entity") { | ||
| 461 | lightboxPopup.titleText = "Rez Certified Permission"; | ||
| 462 | lightboxPopup.bodyText = "You don't have permission to rez certified items in this domain.<br><br>" + | ||
| 463 | "Use the <b>GOTO app</b> to visit another domain or <b>go to your own sandbox.</b>"; | ||
| 464 | lightboxPopup.button2text = "OPEN GOTO"; | ||
| 465 | lightboxPopup.button2method = "sendToParent({method: 'purchases_openGoTo'});"; | ||
| 466 | } else if (msg.itemType === "contentSet") { | ||
| 467 | lightboxPopup.titleText = "Replace Content Permission"; | ||
| 468 | lightboxPopup.bodyText = "You do not have the permission 'Replace Content' in this <b>domain's server settings</b>. The domain owner " + | ||
| 469 | "must enable it for you before you can replace content sets in this domain."; | ||
| 470 | } | ||
| 471 | lightboxPopup.button1text = "CLOSE"; | ||
| 472 | lightboxPopup.button1method = "root.visible = false;" | ||
| 473 | lightboxPopup.visible = true; | ||
| 485 | } else if (msg.method === "setFilterText") { | 474 | } else if (msg.method === "setFilterText") { |
| 486 | filterBar.text = msg.filterText; | 475 | filterBar.text = msg.filterText; |
| 476 | } else if (msg.method === "openPermissionExplanationCard") { | ||
| 477 | for (var i = 0; i < filteredPurchasesModel.count; i++) { | ||
| 478 | if (i !== index || msg.closeAll) { | ||
| 479 | filteredPurchasesModel.setProperty(i, "permissionExplanationCardVisible", false); | ||
| 480 | } else { | ||
| 481 | filteredPurchasesModel.setProperty(i, "permissionExplanationCardVisible", true); | ||
| 482 | } | ||
| 483 | } | ||
| 487 | } | 484 | } |
| 488 | } | 485 | } |
| 489 | } | 486 | } |
| @@ -685,6 +682,7 @@ Rectangle { · 195 unmodified lines | |||
| 685 | filteredPurchasesModel.clear(); | 682 | filteredPurchasesModel.clear(); |
| 686 | for (var i = 0; i < tempPurchasesModel.count; i++) { | 683 | for (var i = 0; i < tempPurchasesModel.count; i++) { |
| 687 | filteredPurchasesModel.append(tempPurchasesModel.get(i)); | 684 | filteredPurchasesModel.append(tempPurchasesModel.get(i)); |
| 685 | filteredPurchasesModel.setProperty(i, 'permissionExplanationCardVisible', false); | ||
| 688 | } | 686 | } |
| 689 | 687 | ||
| 690 | populateDisplayedItemCounts(); | 688 | populateDisplayedItemCounts(); |
| @@ -218,7 +218,7 @@ Item { · 217 unmodified lines | |||
| 218 | readonly property var colorStart: [ colors.white, colors.primaryHighlight, "#d42043", "#343434", Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ] | 218 | readonly property var colorStart: [ colors.white, colors.primaryHighlight, "#d42043", "#343434", Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ] |
| 219 | readonly property var colorFinish: [ colors.lightGrayText, colors.blueAccent, "#94132e", colors.black, Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ] | 219 | readonly property var colorFinish: [ colors.lightGrayText, colors.blueAccent, "#94132e", colors.black, Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ] |
| 220 | readonly property var hoveredColor: [ colorStart[white], colorStart[blue], colorStart[red], colorFinish[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ] | 220 | readonly property var hoveredColor: [ colorStart[white], colorStart[blue], colorStart[red], colorFinish[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ] |
| 221 | readonly property var pressedColor: [ colorFinish[white], colorFinish[blue], colorFinish[red], colorStart[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ] | 221 | readonly property var pressedColor: [ colorFinish[white], colorFinish[blue], colorFinish[red], colorStart[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colors.lightGrayText ] |
| 222 | readonly property var focusedColor: [ colors.lightGray50, colors.blueAccent, colors.redAccent, colors.darkGray, colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ] | 222 | readonly property var focusedColor: [ colors.lightGray50, colors.blueAccent, colors.redAccent, colors.darkGray, colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ] |
| 223 | readonly property var disabledColorStart: [ colorStart[white], colors.baseGrayHighlight] | 223 | readonly property var disabledColorStart: [ colorStart[white], colors.baseGrayHighlight] |
| 224 | readonly property var disabledColorFinish: [ colorFinish[white], colors.baseGrayShadow] | 224 | readonly property var disabledColorFinish: [ colorFinish[white], colors.baseGrayShadow] |
| @@ -354,5 +354,9 @@ Item { · 129 unmodified lines | |||
| 354 | readonly property string wallet: "\ue027" | 354 | readonly property string wallet: "\ue027" |
| 355 | readonly property string paperPlane: "\ue028" | 355 | readonly property string paperPlane: "\ue028" |
| 356 | readonly property string passphrase: "\ue029" | 356 | readonly property string passphrase: "\ue029" |
| 357 | readonly property string globe: "\ue02c" | ||
| 358 | readonly property string wand: "\ue02d" | ||
| 359 | readonly property string hat: "\ue02e" | ||
| 360 | readonly property string install: "\ue02f" | ||
| 357 | } | 361 | } |
| 358 | } | 362 | } |
| @@ -6370,6 +6370,24 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) { · 6369 unmodified lines | |||
| 6370 | return true; | 6370 | return true; |
| 6371 | } | 6371 | } |
| 6372 | 6372 | ||
| 6373 | void Application::replaceDomainContent(const QString& url) { | ||
| 6374 | qCDebug(interfaceapp) << "Attempting to replace domain content: " << url; | ||
| 6375 | QByteArray urlData(url.toUtf8()); | ||
| 6376 | auto limitedNodeList = DependencyManager::get<LimitedNodeList>(); | ||
| 6377 | limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { | ||
| 6378 | return node->getType() == NodeType::EntityServer && node->getActiveSocket(); | ||
| 6379 | }, [&urlData, limitedNodeList](const SharedNodePointer& octreeNode) { | ||
| 6380 | auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, urlData.size(), true); | ||
| 6381 | octreeFilePacket->write(urlData); | ||
| 6382 | limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode); | ||
| 6383 | }); | ||
| 6384 | auto addressManager = DependencyManager::get<AddressManager>(); | ||
| 6385 | addressManager->handleLookupString(DOMAIN_SPAWNING_POINT); | ||
| 6386 | QString newHomeAddress = addressManager->getHost() + DOMAIN_SPAWNING_POINT; | ||
| 6387 | qCDebug(interfaceapp) << "Setting new home bookmark to: " << newHomeAddress; | ||
| 6388 | DependencyManager::get<LocationBookmarks>()->setHomeLocationToAddress(newHomeAddress); | ||
| 6389 | } | ||
| 6390 | |||
| 6373 | bool Application::askToReplaceDomainContent(const QString& url) { | 6391 | bool Application::askToReplaceDomainContent(const QString& url) { |
| 6374 | QString methodDetails; | 6392 | QString methodDetails; |
| 6375 | const int MAX_CHARACTERS_PER_LINE = 90; | 6393 | const int MAX_CHARACTERS_PER_LINE = 90; |
| @@ -6389,21 +6407,7 @@ bool Application::askToReplaceDomainContent(const QString& url) { · 13 unmodified lines | |||
| 6389 | QString details; | 6407 | QString details; |
| 6390 | if (static_cast<QMessageBox::StandardButton>(answer.toInt()) == QMessageBox::Yes) { | 6408 | if (static_cast<QMessageBox::StandardButton>(answer.toInt()) == QMessageBox::Yes) { |
| 6391 | // Given confirmation, send request to domain server to replace content | 6409 | // Given confirmation, send request to domain server to replace content |
| 6392 | qCDebug(interfaceapp) << "Attempting to replace domain content: " << url; | 6410 | replaceDomainContent(url); |
| 6393 | QByteArray urlData(url.toUtf8()); | ||
| 6394 | auto limitedNodeList = DependencyManager::get<LimitedNodeList>(); | ||
| 6395 | limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { | ||
| 6396 | return node->getType() == NodeType::EntityServer && node->getActiveSocket(); | ||
| 6397 | }, [&urlData, limitedNodeList](const SharedNodePointer& octreeNode) { | ||
| 6398 | auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, urlData.size(), true); | ||
| 6399 | octreeFilePacket->write(urlData); | ||
| 6400 | limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode); | ||
| 6401 | }); | ||
| 6402 | auto addressManager = DependencyManager::get<AddressManager>(); | ||
| 6403 | addressManager->handleLookupString(DOMAIN_SPAWNING_POINT); | ||
| 6404 | QString newHomeAddress = addressManager->getHost() + DOMAIN_SPAWNING_POINT; | ||
| 6405 | qCDebug(interfaceapp) << "Setting new home bookmark to: " << newHomeAddress; | ||
| 6406 | DependencyManager::get<LocationBookmarks>()->setHomeLocationToAddress(newHomeAddress); | ||
| 6407 | details = "SuccessfulRequestToReplaceContent"; | 6411 | details = "SuccessfulRequestToReplaceContent"; |
| 6408 | } else { | 6412 | } else { |
| 6409 | details = "UserDeclinedToReplaceContent"; | 6413 | details = "UserDeclinedToReplaceContent"; |
| @@ -288,6 +288,8 @@ public: · 287 unmodified lines | |||
| 288 | 288 | ||
| 289 | bool isServerlessMode() const { return !_serversEnabled; } | 289 | bool isServerlessMode() const { return !_serversEnabled; } |
| 290 | 290 | ||
| 291 | void replaceDomainContent(const QString& url); | ||
| 292 | |||
| 291 | signals: | 293 | signals: |
| 292 | void svoImportRequested(const QString& url); | 294 | void svoImportRequested(const QString& url); |
| 293 | 295 | ||
| @@ -1479,7 +1479,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { · 1478 unmodified lines | |||
| 1479 | }); | 1479 | }); |
| 1480 | saveAvatarUrl(); | 1480 | saveAvatarUrl(); |
| 1481 | emit skeletonChanged(); | 1481 | emit skeletonChanged(); |
| 1482 | 1482 | emit skeletonModelURLChanged(); | |
| 1483 | } | 1483 | } |
| 1484 | 1484 | ||
| 1485 | void MyAvatar::removeAvatarEntities() { | 1485 | void MyAvatar::removeAvatarEntities() { |
| @@ -49,6 +49,7 @@ Handler(balance) · 48 unmodified lines | |||
| 49 | Handler(inventory) | 49 | Handler(inventory) |
| 50 | Handler(transferHfcToNode) | 50 | Handler(transferHfcToNode) |
| 51 | Handler(transferHfcToUsername) | 51 | Handler(transferHfcToUsername) |
| 52 | Handler(alreadyOwned) | ||
| 52 | 53 | ||
| 53 | void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request) { | 54 | void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request) { |
| 54 | auto accountManager = DependencyManager::get<AccountManager>(); | 55 | auto accountManager = DependencyManager::get<AccountManager>(); |
| @@ -336,3 +337,12 @@ void Ledger::transferHfcToUsername(const QString& hfc_key, const QString& userna · 281 unmodified lines | |||
| 336 | auto transactionString = transactionDoc.toJson(QJsonDocument::Compact); | 337 | auto transactionString = transactionDoc.toJson(QJsonDocument::Compact); |
| 337 | signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_user", "transferHfcToUsernameSuccess", "transferHfcToUsernameFailure"); | 338 | signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_user", "transferHfcToUsernameSuccess", "transferHfcToUsernameFailure"); |
| 338 | } | 339 | } |
| 340 | |||
| 341 | void Ledger::alreadyOwned(const QString& marketplaceId) { | ||
| 342 | auto wallet = DependencyManager::get<Wallet>(); | ||
| 343 | QString endpoint = "already_owned"; | ||
| 344 | QJsonObject request; | ||
| 345 | request["public_keys"] = QJsonArray::fromStringList(wallet->listPublicKeys()); | ||
| 346 | request["marketplace_item_id"] = marketplaceId; | ||
| 347 | send(endpoint, "alreadyOwnedSuccess", "alreadyOwnedFailure", QNetworkAccessManager::PutOperation, AccountManagerAuth::Required, request); | ||
| 348 | } | ||
| @@ -35,6 +35,7 @@ public: · 34 unmodified lines | |||
| 35 | void certificateInfo(const QString& certificateId); | 35 | void certificateInfo(const QString& certificateId); |
| 36 | void transferHfcToNode(const QString& hfc_key, const QString& nodeID, const int& amount, const QString& optionalMessage); | 36 | void transferHfcToNode(const QString& hfc_key, const QString& nodeID, const int& amount, const QString& optionalMessage); |
| 37 | void transferHfcToUsername(const QString& hfc_key, const QString& username, const int& amount, const QString& optionalMessage); | 37 | void transferHfcToUsername(const QString& hfc_key, const QString& username, const int& amount, const QString& optionalMessage); |
| 38 | void alreadyOwned(const QString& marketplaceId); | ||
| 38 | 39 | ||
| 39 | enum CertificateStatus { | 40 | enum CertificateStatus { |
| 40 | CERTIFICATE_STATUS_UNKNOWN = 0, | 41 | CERTIFICATE_STATUS_UNKNOWN = 0, |
| @@ -55,6 +56,7 @@ signals: · 14 unmodified lines | |||
| 55 | void certificateInfoResult(QJsonObject result); | 56 | void certificateInfoResult(QJsonObject result); |
| 56 | void transferHfcToNodeResult(QJsonObject result); | 57 | void transferHfcToNodeResult(QJsonObject result); |
| 57 | void transferHfcToUsernameResult(QJsonObject result); | 58 | void transferHfcToUsernameResult(QJsonObject result); |
| 59 | void alreadyOwnedResult(QJsonObject result); | ||
| 58 | 60 | ||
| 59 | void updateCertificateStatus(const QString& certID, uint certStatus); | 61 | void updateCertificateStatus(const QString& certID, uint certStatus); |
| 60 | 62 | ||
| @@ -79,6 +81,8 @@ public slots: · 18 unmodified lines | |||
| 79 | void transferHfcToNodeFailure(QNetworkReply& reply); | 81 | void transferHfcToNodeFailure(QNetworkReply& reply); |
| 80 | void transferHfcToUsernameSuccess(QNetworkReply& reply); | 82 | void transferHfcToUsernameSuccess(QNetworkReply& reply); |
| 81 | void transferHfcToUsernameFailure(QNetworkReply& reply); | 83 | void transferHfcToUsernameFailure(QNetworkReply& reply); |
| 84 | void alreadyOwnedSuccess(QNetworkReply& reply); | ||
| 85 | void alreadyOwnedFailure(QNetworkReply& reply); | ||
| 82 | 86 | ||
| 83 | private: | 87 | private: |
| 84 | QJsonObject apiResponse(const QString& label, QNetworkReply& reply); | 88 | QJsonObject apiResponse(const QString& label, QNetworkReply& reply); |
| @@ -15,6 +15,8 @@ · 14 unmodified lines | |||
| 15 | #include "Ledger.h" | 15 | #include "Ledger.h" |
| 16 | #include "Wallet.h" | 16 | #include "Wallet.h" |
| 17 | #include <AccountManager.h> | 17 | #include <AccountManager.h> |
| 18 | #include <Application.h> | ||
| 19 | #include <UserActivityLogger.h> | ||
| 18 | 20 | ||
| 19 | QmlCommerce::QmlCommerce() { | 21 | QmlCommerce::QmlCommerce() { |
| 20 | auto ledger = DependencyManager::get<Ledger>(); | 22 | auto ledger = DependencyManager::get<Ledger>(); |
| @@ -28,9 +30,11 @@ QmlCommerce::QmlCommerce() { · 7 unmodified lines | |||
| 28 | connect(ledger.data(), &Ledger::accountResult, this, &QmlCommerce::accountResult); | 30 | connect(ledger.data(), &Ledger::accountResult, this, &QmlCommerce::accountResult); |
| 29 | connect(wallet.data(), &Wallet::walletStatusResult, this, &QmlCommerce::walletStatusResult); | 31 | connect(wallet.data(), &Wallet::walletStatusResult, this, &QmlCommerce::walletStatusResult); |
| 30 | connect(ledger.data(), &Ledger::certificateInfoResult, this, &QmlCommerce::certificateInfoResult); | 32 | connect(ledger.data(), &Ledger::certificateInfoResult, this, &QmlCommerce::certificateInfoResult); |
| 33 | connect(ledger.data(), &Ledger::alreadyOwnedResult, this, &QmlCommerce::alreadyOwnedResult); | ||
| 31 | connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus); | 34 | connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus); |
| 32 | connect(ledger.data(), &Ledger::transferHfcToNodeResult, this, &QmlCommerce::transferHfcToNodeResult); | 35 | connect(ledger.data(), &Ledger::transferHfcToNodeResult, this, &QmlCommerce::transferHfcToNodeResult); |
| 33 | connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult); | 36 | connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult); |
| 37 | connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult); | ||
| 34 | 38 | ||
| 35 | auto accountManager = DependencyManager::get<AccountManager>(); | 39 | auto accountManager = DependencyManager::get<AccountManager>(); |
| 36 | connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() { | 40 | connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() { |
| @@ -163,3 +167,19 @@ void QmlCommerce::transferHfcToUsername(const QString& username, const int& amou · 126 unmodified lines | |||
| 163 | QString key = keys[0]; | 167 | QString key = keys[0]; |
| 164 | ledger->transferHfcToUsername(key, username, amount, optionalMessage); | 168 | ledger->transferHfcToUsername(key, username, amount, optionalMessage); |
| 165 | } | 169 | } |
| 170 | |||
| 171 | void QmlCommerce::replaceContentSet(const QString& itemHref) { | ||
| 172 | qApp->replaceDomainContent(itemHref); | ||
| 173 | QJsonObject messageProperties = { | ||
| 174 | { "status", "SuccessfulRequestToReplaceContent" }, | ||
| 175 | { "content_set_url", itemHref } | ||
| 176 | }; | ||
| 177 | UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties); | ||
| 178 | |||
| 179 | emit contentSetChanged(itemHref); | ||
| 180 | } | ||
| 181 | |||
| 182 | void QmlCommerce::alreadyOwned(const QString& marketplaceId) { | ||
| 183 | auto ledger = DependencyManager::get<Ledger>(); | ||
| 184 | ledger->alreadyOwned(marketplaceId); | ||
| 185 | } | ||
| @@ -42,12 +42,15 @@ signals: · 41 unmodified lines | |||
| 42 | void historyResult(QJsonObject result); | 42 | void historyResult(QJsonObject result); |
| 43 | void accountResult(QJsonObject result); | 43 | void accountResult(QJsonObject result); |
| 44 | void certificateInfoResult(QJsonObject result); | 44 | void certificateInfoResult(QJsonObject result); |
| 45 | void alreadyOwnedResult(QJsonObject result); | ||
| 45 | 46 | ||
| 46 | void updateCertificateStatus(const QString& certID, uint certStatus); | 47 | void updateCertificateStatus(const QString& certID, uint certStatus); |
| 47 | 48 | ||
| 48 | void transferHfcToNodeResult(QJsonObject result); | 49 | void transferHfcToNodeResult(QJsonObject result); |
| 49 | void transferHfcToUsernameResult(QJsonObject result); | 50 | void transferHfcToUsernameResult(QJsonObject result); |
| 50 | 51 | ||
| 52 | void contentSetChanged(const QString& contentSetHref); | ||
| 53 | |||
| 51 | protected: | 54 | protected: |
| 52 | Q_INVOKABLE void getWalletStatus(); | 55 | Q_INVOKABLE void getWalletStatus(); |
| 53 | 56 | ||
| @@ -68,9 +71,13 @@ protected: · 14 unmodified lines | |||
| 68 | Q_INVOKABLE void account(); | 71 | Q_INVOKABLE void account(); |
| 69 | 72 | ||
| 70 | Q_INVOKABLE void certificateInfo(const QString& certificateId); | 73 | Q_INVOKABLE void certificateInfo(const QString& certificateId); |
| 74 | Q_INVOKABLE void alreadyOwned(const QString& marketplaceId); | ||
| 71 | 75 | ||
| 72 | Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage); | 76 | Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage); |
| 73 | Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage); | 77 | Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage); |
| 78 | |||
| 79 | |||
| 80 | Q_INVOKABLE void replaceContentSet(const QString& itemHref); | ||
| 74 | }; | 81 | }; |
| 75 | 82 | ||
| 76 | #endif // hifi_QmlCommerce_h | 83 | #endif // hifi_QmlCommerce_h |
| @@ -38,7 +38,7 @@ class AccountServicesScriptingInterface : public QObject { · 37 unmodified lines | |||
| 38 | Q_PROPERTY(QString username READ getUsername NOTIFY myUsernameChanged) | 38 | Q_PROPERTY(QString username READ getUsername NOTIFY myUsernameChanged) |
| 39 | Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loggedInChanged) | 39 | Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loggedInChanged) |
| 40 | Q_PROPERTY(QString findableBy READ getFindableBy WRITE setFindableBy NOTIFY findableByChanged) | 40 | Q_PROPERTY(QString findableBy READ getFindableBy WRITE setFindableBy NOTIFY findableByChanged) |
| 41 | Q_PROPERTY(QUrl metaverseServerURL READ getMetaverseServerURL) | 41 | Q_PROPERTY(QUrl metaverseServerURL READ getMetaverseServerURL CONSTANT) |
| 42 | 42 | ||
| 43 | public: | 43 | public: |
| 44 | static AccountServicesScriptingInterface* getInstance(); | 44 | static AccountServicesScriptingInterface* getInstance(); |
| @@ -373,7 +373,7 @@ class AvatarData : public QObject, public SpatiallyNestable { · 372 unmodified lines | |||
| 373 | // The result is unique among all avatars present at the time. | 373 | // The result is unique among all avatars present at the time. |
| 374 | Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName NOTIFY sessionDisplayNameChanged) | 374 | Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName NOTIFY sessionDisplayNameChanged) |
| 375 | Q_PROPERTY(bool lookAtSnappingEnabled MEMBER _lookAtSnappingEnabled NOTIFY lookAtSnappingChanged) | 375 | Q_PROPERTY(bool lookAtSnappingEnabled MEMBER _lookAtSnappingEnabled NOTIFY lookAtSnappingChanged) |
| 376 | Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript) | 376 | Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged) |
| 377 | Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData WRITE setAttachmentData) | 377 | Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData WRITE setAttachmentData) |
| 378 | 378 | ||
| 379 | Q_PROPERTY(QStringList jointNames READ getJointNames) | 379 | Q_PROPERTY(QStringList jointNames READ getJointNames) |
| @@ -702,6 +702,7 @@ public: · 322 unmodified lines | |||
| 702 | signals: | 702 | signals: |
| 703 | void displayNameChanged(); | 703 | void displayNameChanged(); |
| 704 | void sessionDisplayNameChanged(); | 704 | void sessionDisplayNameChanged(); |
| 705 | void skeletonModelURLChanged(); | ||
| 705 | void lookAtSnappingChanged(bool enabled); | 706 | void lookAtSnappingChanged(bool enabled); |
| 706 | void sessionUUIDChanged(); | 707 | void sessionUUIDChanged(); |
| 707 | 708 | ||
| @@ -16,6 +16,7 @@ ScriptAvatarData::ScriptAvatarData(AvatarSharedPointer avatarData) : · 15 unmodified lines | |||
| 16 | { | 16 | { |
| 17 | QObject::connect(avatarData.get(), &AvatarData::displayNameChanged, this, &ScriptAvatarData::displayNameChanged); | 17 | QObject::connect(avatarData.get(), &AvatarData::displayNameChanged, this, &ScriptAvatarData::displayNameChanged); |
| 18 | QObject::connect(avatarData.get(), &AvatarData::sessionDisplayNameChanged, this, &ScriptAvatarData::sessionDisplayNameChanged); | 18 | QObject::connect(avatarData.get(), &AvatarData::sessionDisplayNameChanged, this, &ScriptAvatarData::sessionDisplayNameChanged); |
| 19 | QObject::connect(avatarData.get(), &AvatarData::skeletonModelURLChanged, this, &ScriptAvatarData::skeletonModelURLChanged); | ||
| 19 | QObject::connect(avatarData.get(), &AvatarData::lookAtSnappingChanged, this, &ScriptAvatarData::lookAtSnappingChanged); | 20 | QObject::connect(avatarData.get(), &AvatarData::lookAtSnappingChanged, this, &ScriptAvatarData::lookAtSnappingChanged); |
| 20 | } | 21 | } |
| 21 | 22 | ||
| @@ -51,7 +51,7 @@ class ScriptAvatarData : public QObject { · 50 unmodified lines | |||
| 51 | // | 51 | // |
| 52 | // ATTACHMENT AND JOINT PROPERTIES | 52 | // ATTACHMENT AND JOINT PROPERTIES |
| 53 | // | 53 | // |
| 54 | Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript) | 54 | Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged) |
| 55 | Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData) | 55 | Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData) |
| 56 | Q_PROPERTY(QStringList jointNames READ getJointNames) | 56 | Q_PROPERTY(QStringList jointNames READ getJointNames) |
| 57 | 57 | ||
| @@ -132,6 +132,7 @@ public: · 74 unmodified lines | |||
| 132 | signals: | 132 | signals: |
| 133 | void displayNameChanged(); | 133 | void displayNameChanged(); |
| 134 | void sessionDisplayNameChanged(); | 134 | void sessionDisplayNameChanged(); |
| 135 | void skeletonModelURLChanged(); | ||
| 135 | void lookAtSnappingChanged(bool enabled); | 136 | void lookAtSnappingChanged(bool enabled); |
| 136 | 137 | ||
| 137 | public slots: | 138 | public slots: |
| @@ -101,6 +101,11 @@ bool EntityScriptingInterface::canWriteAssets() { · 100 unmodified lines | |||
| 101 | return nodeList->getThisNodeCanWriteAssets(); | 101 | return nodeList->getThisNodeCanWriteAssets(); |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | bool EntityScriptingInterface::canReplaceContent() { | ||
| 105 | auto nodeList = DependencyManager::get<NodeList>(); | ||
| 106 | return nodeList->getThisNodeCanReplaceContent(); | ||
| 107 | } | ||
| 108 | |||
| 104 | void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) { | 109 | void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) { |
| 105 | if (_entityTree) { | 110 | if (_entityTree) { |
| 106 | disconnect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity); | 111 | disconnect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity); |
| @@ -144,6 +144,12 @@ public slots: · 143 unmodified lines | |||
| 144 | */ | 144 | */ |
| 145 | Q_INVOKABLE bool canWriteAssets(); | 145 | Q_INVOKABLE bool canWriteAssets(); |
| 146 | 146 | ||
| 147 | /**jsdoc | ||
| 148 | * @function Entities.canReplaceContent | ||
| 149 | * @return {bool} `true` if the DomainServer will allow this Node/Avatar to replace the domain's content set | ||
| 150 | */ | ||
| 151 | Q_INVOKABLE bool canReplaceContent(); | ||
| 152 | |||
| 147 | /**jsdoc | 153 | /**jsdoc |
| 148 | * Add a new entity with the specified properties. If `clientOnly` is true, the entity will | 154 | * Add a new entity with the specified properties. If `clientOnly` is true, the entity will |
| 149 | * not be sent to the server and will only be visible/accessible on the local client. | 155 | * not be sent to the server and will only be visible/accessible on the local client. |
| @@ -89,7 +89,9 @@ float evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets · 88 unmodified lines | |||
| 89 | 89 | ||
| 90 | float evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDepth, vec3 worldNormal) { | 90 | float evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDepth, vec3 worldNormal) { |
| 91 | ShadowSampleOffsets offsets = evalShadowFilterOffsets(worldPosition); | 91 | ShadowSampleOffsets offsets = evalShadowFilterOffsets(worldPosition); |
| 92 | vec4 cascadeShadowCoords[2] = { vec4(0), vec4(0) }; | 92 | vec4 cascadeShadowCoords[2]; |
| 93 | cascadeShadowCoords[0] = vec4(0); | ||
| 94 | cascadeShadowCoords[1] = vec4(0); | ||
| 93 | ivec2 cascadeIndices; | 95 | ivec2 cascadeIndices; |
| 94 | float cascadeMix = determineShadowCascadesOnPixel(worldPosition, viewDepth, cascadeShadowCoords, cascadeIndices); | 96 | float cascadeMix = determineShadowCascadesOnPixel(worldPosition, viewDepth, cascadeShadowCoords, cascadeIndices); |
| 95 | 97 | ||
| @@ -129,6 +129,7 @@ QUrl PathUtils::expandToAppAbsolutePath(const QUrl& fileUrl) { · 128 unmodified lines | |||
| 129 | } | 129 | } |
| 130 | return url; | 130 | return url; |
| 131 | } | 131 | } |
| 132 | |||
| 132 | const QString& PathUtils::qmlBaseUrl() { | 133 | const QString& PathUtils::qmlBaseUrl() { |
| 133 | static const QString staticResourcePath = resourcesUrl() + "qml/"; | 134 | static const QString staticResourcePath = resourcesUrl() + "qml/"; |
| 134 | return staticResourcePath; | 135 | return staticResourcePath; |
| @@ -75,11 +75,11 @@ var selectionDisplay = null; // for gridTool.js to ignore · 74 unmodified lines | |||
| 75 | tablet.pushOntoStack(MARKETPLACE_CHECKOUT_QML_PATH); | 75 | tablet.pushOntoStack(MARKETPLACE_CHECKOUT_QML_PATH); |
| 76 | tablet.sendToQml({ | 76 | tablet.sendToQml({ |
| 77 | method: 'updateCheckoutQML', params: { | 77 | method: 'updateCheckoutQML', params: { |
| 78 | itemId: '0d90d21c-ce7a-4990-ad18-e9d2cf991027', | 78 | itemId: '424611a2-73d0-4c03-9087-26a6a279257b', |
| 79 | itemName: 'Test Flaregun', | 79 | itemName: '2018-02-15 Finnegon', |
| 80 | itemPrice: (debugError ? 10 : 17), | 80 | itemPrice: (debugError ? 10 : 3), |
| 81 | itemHref: 'http://mpassets.highfidelity.com/0d90d21c-ce7a-4990-ad18-e9d2cf991027-v1/flaregun.json', | 81 | itemHref: 'http://devmpassets.highfidelity.com/424611a2-73d0-4c03-9087-26a6a279257b-v1/finnigon.fst', |
| 82 | categories: ["Wearables", "Miscellaneous"] | 82 | categories: ["Miscellaneous"] |
| 83 | } | 83 | } |
| 84 | }); | 84 | }); |
| 85 | } | 85 | } |
| @@ -233,13 +233,19 @@ var selectionDisplay = null; // for gridTool.js to ignore · 147 unmodified lines | |||
| 233 | return position; | 233 | return position; |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | function rezEntity(itemHref, isWearable) { | 236 | function rezEntity(itemHref, itemType) { |
| 237 | var isWearable = itemType === "wearable"; | ||
| 237 | var success = Clipboard.importEntities(itemHref); | 238 | var success = Clipboard.importEntities(itemHref); |
| 238 | var wearableLocalPosition = null; | 239 | var wearableLocalPosition = null; |
| 239 | var wearableLocalRotation = null; | 240 | var wearableLocalRotation = null; |
| 240 | var wearableLocalDimensions = null; | 241 | var wearableLocalDimensions = null; |
| 241 | var wearableDimensions = null; | 242 | var wearableDimensions = null; |
| 242 | 243 | ||
| 244 | if (itemType === "contentSet") { | ||
| 245 | console.log("Item is a content set; codepath shouldn't go here.") | ||
| 246 | return; | ||
| 247 | } | ||
| 248 | |||
| 243 | if (isWearable) { | 249 | if (isWearable) { |
| 244 | var wearableTransforms = Settings.getValue("io.highfidelity.avatarStore.checkOut.transforms"); | 250 | var wearableTransforms = Settings.getValue("io.highfidelity.avatarStore.checkOut.transforms"); |
| 245 | if (!wearableTransforms) { | 251 | if (!wearableTransforms) { |
| @@ -545,7 +551,11 @@ var selectionDisplay = null; // for gridTool.js to ignore · 299 unmodified lines | |||
| 545 | break; | 551 | break; |
| 546 | case 'checkout_rezClicked': | 552 | case 'checkout_rezClicked': |
| 547 | case 'purchases_rezClicked': | 553 | case 'purchases_rezClicked': |
| 548 | rezEntity(message.itemHref, message.isWearable); | 554 | if (message.itemType === "app") { |
| 555 | console.log("How did you get here? You can't buy apps yet!"); | ||
| 556 | } else { | ||
| 557 | rezEntity(message.itemHref, message.itemType); | ||
| 558 | } | ||
| 549 | break; | 559 | break; |
| 550 | case 'header_marketplaceImageClicked': | 560 | case 'header_marketplaceImageClicked': |
| 551 | case 'purchases_backClicked': | 561 | case 'purchases_backClicked': |