Merge branch 'master' of github.com:highfidelity/hifi into brown

This commit is contained in:
Sam Gateau 2019-02-06 12:09:38 -08:00
commit 8ec9c8502d
28 changed files with 2676 additions and 459 deletions

View file

@ -662,7 +662,7 @@ Rectangle {
anchors.right: parent.right;
text: "Cancel"
onClicked: {
sendToScript({method: 'checkout_cancelClicked', params: itemId});
sendToScript({method: 'checkout_cancelClicked', itemId: itemId});
}
}
}

View file

@ -24,11 +24,8 @@ Item {
HifiConstants { id: hifi; }
id: root;
property string referrerURL: (Account.metaverseServerURL + "/marketplace?");
readonly property int additionalDropdownHeight: usernameDropdown.height - myUsernameButton.anchors.bottomMargin;
property alias usernameDropdownVisible: usernameDropdown.visible;
height: mainContainer.height + additionalDropdownHeight;
height: mainContainer.height;
Connections {
target: Commerce;
@ -93,77 +90,7 @@ Item {
MouseArea {
anchors.fill: parent;
onClicked: {
sendToParent({method: "header_marketplaceImageClicked", referrerURL: root.referrerURL});
}
}
}
Item {
id: buttonAndUsernameContainer;
anchors.left: marketplaceHeaderImage.right;
anchors.leftMargin: 8;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 10;
anchors.right: securityImage.left;
anchors.rightMargin: 6;
TextMetrics {
id: textMetrics;
font.family: "Raleway"
text: usernameText.text;
}
Rectangle {
id: myUsernameButton;
anchors.right: parent.right;
anchors.verticalCenter: parent.verticalCenter;
height: 40;
width: usernameText.width + 25;
color: "white";
radius: 4;
border.width: 1;
border.color: hifi.colors.lightGray;
// Username Text
RalewayRegular {
id: usernameText;
text: Account.username;
// Text size
size: 18;
// Style
color: hifi.colors.baseGray;
elide: Text.ElideRight;
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
width: Math.min(textMetrics.width + 25, 110);
// Anchors
anchors.centerIn: parent;
rightPadding: 10;
}
HiFiGlyphs {
id: dropdownIcon;
text: hifi.glyphs.caratDn;
// Size
size: 50;
// Anchors
anchors.right: parent.right;
anchors.rightMargin: -14;
anchors.verticalCenter: parent.verticalCenter;
horizontalAlignment: Text.AlignHCenter;
// Style
color: hifi.colors.baseGray;
}
MouseArea {
anchors.fill: parent;
hoverEnabled: enabled;
onClicked: {
usernameDropdown.visible = !usernameDropdown.visible;
}
onEntered: usernameText.color = hifi.colors.baseGrayShadow;
onExited: usernameText.color = hifi.colors.baseGray;
sendToParent({method: "header_marketplaceImageClicked"});
}
}
}
@ -205,92 +132,6 @@ Item {
}
}
Item {
id: usernameDropdown;
z: 998;
visible: false;
anchors.top: buttonAndUsernameContainer.bottom;
anchors.topMargin: -buttonAndUsernameContainer.anchors.bottomMargin;
anchors.right: buttonAndUsernameContainer.right;
height: childrenRect.height;
width: 150;
Rectangle {
id: myItemsButton;
color: hifi.colors.white;
anchors.top: parent.top;
anchors.left: parent.left;
anchors.right: parent.right;
height: 50;
RalewaySemiBold {
anchors.fill: parent;
text: "My Submissions"
color: hifi.colors.baseGray;
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
size: 18;
}
MouseArea {
anchors.fill: parent;
hoverEnabled: true;
onEntered: {
myItemsButton.color = hifi.colors.blueHighlight;
}
onExited: {
myItemsButton.color = hifi.colors.white;
}
onClicked: {
sendToParent({method: "header_myItemsClicked"});
}
}
}
Rectangle {
id: logOutButton;
color: hifi.colors.white;
anchors.top: myItemsButton.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
height: 50;
RalewaySemiBold {
anchors.fill: parent;
text: "Log Out"
color: hifi.colors.baseGray;
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
size: 18;
}
MouseArea {
anchors.fill: parent;
hoverEnabled: true;
onEntered: {
logOutButton.color = hifi.colors.blueHighlight;
}
onExited: {
logOutButton.color = hifi.colors.white;
}
onClicked: {
Account.logOut();
}
}
}
}
DropShadow {
z: 997;
visible: usernameDropdown.visible;
anchors.fill: usernameDropdown;
horizontalOffset: 3;
verticalOffset: 3;
radius: 8.0;
samples: 17;
color: "#80000000";
source: usernameDropdown;
}
}

View file

@ -22,7 +22,6 @@ Rectangle {
HifiConstants { id: hifi; }
id: root;
property string marketplaceUrl: "";
property string entityId: "";
property string certificateId: "";
property string itemName: "--";
@ -30,6 +29,7 @@ Rectangle {
property string itemEdition: "--";
property string dateAcquired: "--";
property string itemCost: "--";
property string marketplace_item_id: "";
property string certTitleTextColor: hifi.colors.darkGray;
property string certTextColor: hifi.colors.white;
property string infoTextColor: hifi.colors.blueAccent;
@ -69,7 +69,7 @@ Rectangle {
errorText.text = "Information about this certificate is currently unavailable. Please try again later.";
}
} else {
root.marketplaceUrl = result.data.marketplace_item_url;
root.marketplace_item_id = result.data.marketplace_item_id;
root.isMyCert = result.isMyCert ? result.isMyCert : false;
if (root.certInfoReplaceMode > 3) {
@ -352,7 +352,7 @@ Rectangle {
anchors.fill: parent;
hoverEnabled: enabled;
onClicked: {
sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', marketplaceUrl: root.marketplaceUrl});
sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', itemId: root.marketplace_item_id});
}
onEntered: itemName.color = hifi.colors.blueHighlight;
onExited: itemName.color = root.certTextColor;
@ -391,7 +391,7 @@ Rectangle {
// "Show In Marketplace" button
HifiControlsUit.Button {
id: showInMarketplaceButton;
enabled: root.marketplaceUrl;
enabled: root.marketplace_item_id && marketplace_item_id !== "";
color: hifi.buttons.blue;
colorScheme: hifi.colorSchemes.light;
anchors.bottom: parent.bottom;
@ -401,7 +401,7 @@ Rectangle {
height: 40;
text: "View In Market"
onClicked: {
sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', marketplaceUrl: root.marketplaceUrl});
sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', itemId: root.marketplace_item_id});
}
}
}
@ -620,7 +620,7 @@ Rectangle {
root.itemOwner = "--";
root.itemEdition = "--";
root.dateAcquired = "--";
root.marketplaceUrl = "";
root.marketplace_item_id = "";
root.itemCost = "--";
root.isMyCert = false;
errorText.text = "";

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,648 @@
//
// MarketplaceListItem.qml
// qml/hifi/commerce/marketplace
//
// MarketplaceListItem
//
// Created by Roxanne Skelly on 2019-01-22
// Copyright 2019 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import Hifi 1.0 as Hifi
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0
import QtWebEngine 1.5
import stylesUit 1.0
import controlsUit 1.0 as HifiControlsUit
import "../../../controls" as HifiControls
import "../common" as HifiCommerceCommon
import "qrc:////qml//hifi//models" as HifiModels // Absolute path so the same code works everywhere.
import "../common/sendAsset"
import "../.." as HifiCommon
Rectangle {
id: root;
property string item_id: ""
property string image_url: ""
property string name: ""
property int likes: 0
property bool liked: false
property string creator: ""
property var categories: []
property int price: 0
property var attributions: []
property string description: ""
property string license: ""
property string posted: ""
property bool available: false
property string created_at: ""
property bool isLoggedIn: false;
property int edition: -1;
property bool supports3DHTML: false;
onCategoriesChanged: {
categoriesListModel.clear();
categories.forEach(function(category) {
categoriesListModel.append({"category":category});
});
}
onDescriptionChanged: {
if(root.supports3DHTML) {
descriptionTextModel.clear();
descriptionTextModel.append({text: description});
} else {
descriptionText.text = description;
}
}
onAttributionsChanged: {
attributionsModel.clear();
if(root.attributions) {
root.attributions.forEach(function(attribution) {
attributionsModel.append(attribution);
});
}
footer.evalHeight();
}
signal buy()
signal categoryClicked(string category)
signal showLicense(string url)
HifiConstants {
id: hifi
}
Connections {
target: MarketplaceScriptingInterface
onMarketplaceItemLikeResult: {
if (result.status !== 'success') {
console.log("Like/Unlike item", result.data.message);
} else {
root.liked = !root.liked;
root.likes = root.liked ? root.likes + 1 : root.likes - 1;
}
}
}
function getFormattedDate(timestamp) {
function addLeadingZero(n) {
return n < 10 ? '0' + n : '' + n;
}
var a = new Date(timestamp);
var year = a.getFullYear();
var month = addLeadingZero(a.getMonth() + 1);
var day = addLeadingZero(a.getDate());
var hour = a.getHours();
var drawnHour = hour;
if (hour === 0) {
drawnHour = 12;
} else if (hour > 12) {
drawnHour -= 12;
}
drawnHour = addLeadingZero(drawnHour);
var amOrPm = "AM";
if (hour >= 12) {
amOrPm = "PM";
}
var min = addLeadingZero(a.getMinutes());
var sec = addLeadingZero(a.getSeconds());
return a.toDateString() + " " + drawnHour + ':' + min + amOrPm;
}
function evalHeight() {
height = footer.y - header.y + footer.height;
}
signal resized()
onHeightChanged: {
resized();
}
anchors {
left: parent.left
right: parent.right
leftMargin: 15
rightMargin: 15
}
height: footer.y - header.y + footer.height
Rectangle {
id: header
anchors {
left: parent.left
right: parent.right
top: parent.top
}
height: 50
RalewaySemiBold {
id: nameText
anchors {
top: parent.top
left: parent.left
bottom: parent.bottom
}
width: paintedWidth
text: root.name
size: 24
color: hifi.colors.baseGray
verticalAlignment: Text.AlignVCenter
}
Item {
id: likes
anchors {
top: parent.top
right: parent.right
bottom: parent.bottom
rightMargin: 5
}
RalewaySemiBold {
id: heart
anchors {
top: parent.top
right: parent.right
rightMargin: 0
verticalCenter: parent.verticalCenter
}
text: "\u2665"
size: 20
horizontalAlignment: Text.AlignHCenter
color: root.liked ? hifi.colors.redAccent : hifi.colors.lightGrayText
}
RalewaySemiBold {
id: likesText
anchors {
top: parent.top
right: heart.left
rightMargin: 5
leftMargin: 15
bottom: parent.bottom
}
width: paintedWidth
text: root.likes
size: hifi.fontSizes.overlayTitle
color: hifi.colors.baseGray
verticalAlignment: Text.AlignVCenter
}
MouseArea {
anchors {
left: likesText.left
right: heart.right
top: likesText.top
bottom: likesText.bottom
}
onClicked: {
if (isLoggedIn) {
MarketplaceScriptingInterface.marketplaceItemLike(root.item_id, !root.liked);
}
}
}
}
}
Image {
id: itemImage
anchors {
top: header.bottom
left: parent.left
right: parent.right
}
height: width*0.5625
source: root.image_url
fillMode: Image.PreserveAspectCrop;
}
Item {
id: footer
anchors {
left: parent.left;
right: parent.right;
top: itemImage.bottom;
}
height: categoriesList.y - buyButton.y + categoriesList.height
function evalHeight() {
height = categoriesList.y - buyButton.y + categoriesList.height;
console.log("HEIGHT: " + height);
}
HifiControlsUit.Button {
id: buyButton
anchors {
right: parent.right
top: parent.top
left: parent.left
topMargin: 15
}
height: 50
text: root.edition >= 0 ? "UPGRADE FOR FREE" : (root.available ? (root.price ? root.price : "FREE") : "UNAVAILABLE (not for sale)")
enabled: root.edition >= 0 || root.available
buttonGlyph: root.available ? (root.price ? hifi.glyphs.hfc : "") : ""
color: hifi.buttons.blue
onClicked: root.buy();
}
Item {
id: creatorItem
anchors {
top: buyButton.bottom
leftMargin: 15
topMargin: 15
}
width: parent.width
height: childrenRect.height
RalewaySemiBold {
id: creatorLabel
anchors.top: parent.top
anchors.left: parent.left
width: paintedWidth
text: "CREATOR:"
size: 14
color: hifi.colors.lightGrayText
verticalAlignment: Text.AlignVCenter
}
RalewaySemiBold {
id: creatorText
anchors {
top: creatorLabel.bottom
left: parent.left
topMargin: 10
}
width: paintedWidth
text: root.creator
size: 18
color: hifi.colors.blueHighlight
verticalAlignment: Text.AlignVCenter
}
}
Item {
id: posted
anchors {
top: creatorItem.bottom
leftMargin: 15
topMargin: 15
}
width: parent.width
height: childrenRect.height
RalewaySemiBold {
id: postedLabel
anchors.top: parent.top
anchors.left: parent.left
width: paintedWidth
text: "POSTED:"
size: 14
color: hifi.colors.lightGrayText
verticalAlignment: Text.AlignVCenter
}
RalewaySemiBold {
id: created_at
anchors {
top: postedLabel.bottom
left: parent.left
right: parent.right
topMargin: 5
}
text: { getFormattedDate(root.created_at); }
size: 14
color: hifi.colors.lightGray
verticalAlignment: Text.AlignVCenter
}
}
Rectangle {
anchors {
top: posted.bottom
leftMargin: 15
topMargin: 15
}
width: parent.width
height: 1
color: hifi.colors.lightGrayText
}
Item {
id: attributions
anchors {
top: posted.bottom
topMargin: 30
left: parent.left
right: parent.right
}
width: parent.width
height: attributionsModel.count > 0 ? childrenRect.height : 0
visible: attributionsModel.count > 0
RalewaySemiBold {
id: attributionsLabel
anchors.top: parent.top
anchors.left: parent.left
width: paintedWidth
height: paintedHeight
text: "ATTRIBUTIONS:"
size: 14
color: hifi.colors.lightGrayText
verticalAlignment: Text.AlignVCenter
}
ListModel {
id: attributionsModel
}
ListView {
anchors {
left: parent.left
right: parent.right
top: attributionsLabel.bottom
bottomMargin: 15
}
height: 24*model.count+10
model: attributionsModel
delegate: Item {
height: 24
width: parent.width
RalewaySemiBold {
id: attributionName
anchors.leftMargin: 15
height: 24
width: parent.width
text: model.name
elide: Text.ElideRight
size: 14
color: model.link ? hifi.colors.blueHighlight : hifi.colors.baseGray
verticalAlignment: Text.AlignVCenter
MouseArea {
anchors.fill: parent
onClicked: {
if (model.link) {
sendToScript({method: 'marketplace_open_link', link: model.link});
}
}
}
}
}
}
Rectangle {
anchors {
bottom: attributions.bottom
leftMargin: 15
}
width: parent.width
height: 1
color: hifi.colors.lightGrayText
}
}
Item {
id: licenseItem;
anchors {
top: attributions.bottom
left: parent.left
topMargin: 15
}
width: parent.width
height: childrenRect.height
RalewaySemiBold {
id: licenseLabel
anchors.top: parent.top;
anchors.left: parent.left;
width: paintedWidth;
text: "SHARED UNDER:";
size: 14;
color: hifi.colors.lightGrayText;
verticalAlignment: Text.AlignVCenter;
}
RalewaySemiBold {
id: licenseText
anchors.top: licenseLabel.bottom
anchors.left: parent.left
anchors.topMargin: 5
width: paintedWidth
text: root.license
size: 14
color: hifi.colors.lightGray
verticalAlignment: Text.AlignVCenter
}
RalewaySemiBold {
id: licenseHelp
anchors.top: licenseText.bottom
anchors.left: parent.left
anchors.topMargin: 5
width: paintedWidth
text: "More about this license"
size: 14
color: hifi.colors.blueHighlight
verticalAlignment: Text.AlignVCenter
MouseArea {
anchors.fill: parent
onClicked: {
licenseInfo.visible = true;
var url;
if (root.license === "No Rights Reserved (CC0)") {
url = "https://creativecommons.org/publicdomain/zero/1.0/"
} else if (root.license === "Attribution (CC BY)") {
url = "https://creativecommons.org/licenses/by/4.0/legalcode.txt"
} else if (root.license === "Attribution-ShareAlike (CC BY-SA)") {
url = "https://creativecommons.org/licenses/by-sa/4.0/legalcode.txt"
} else if (root.license === "Attribution-NoDerivs (CC BY-ND)") {
url = "https://creativecommons.org/licenses/by-nd/4.0/legalcode.txt"
} else if (root.license === "Attribution-NonCommercial (CC BY-NC)") {
url = "https://creativecommons.org/licenses/by-nc/4.0/legalcode.txt"
} else if (root.license === "Attribution-NonCommercial-ShareAlike (CC BY-NC-SA)") {
url = "https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt"
} else if (root.license === "Attribution-NonCommercial-NoDerivs (CC BY-NC-ND)") {
url = "https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode.txt"
} else if (root.license === "Proof of Provenance License (PoP License)") {
url = "https://digitalassetregistry.com/PoP-License/v1/"
}
if(url) {
showLicense(url)
}
}
}
}
}
Item {
id: descriptionItem
property string text: ""
anchors {
top: licenseItem.bottom
topMargin: 15
left: parent.left
right: parent.right
}
height: childrenRect.height
onHeightChanged: {
footer.evalHeight();
}
RalewaySemiBold {
id: descriptionLabel
anchors.top: parent.top
anchors.left: parent.left
width: paintedWidth
height: 20
text: "DESCRIPTION:"
size: 14
color: hifi.colors.lightGrayText
verticalAlignment: Text.AlignVCenter
}
RalewaySemiBold {
id: descriptionText
anchors.top: descriptionLabel.bottom
anchors.left: parent.left
anchors.topMargin: 5
width: parent.width
text: root.description
size: 14
color: hifi.colors.lightGray
linkColor: hifi.colors.blueHighlight
verticalAlignment: Text.AlignVCenter
textFormat: Text.RichText
wrapMode: Text.Wrap
onLinkActivated: {
sendToScript({method: 'marketplace_open_link', link: link});
}
onHeightChanged: { footer.evalHeight(); }
}
}
Item {
id: categoriesList
anchors {
top: descriptionItem.bottom
topMargin: 15
left: parent.left
right: parent.right
}
width: parent.width
height: categoriesListModel.count*24 + categoryLabel.height + (isLoggedIn ? 50 : 150)
onHeightChanged: { footer.evalHeight(); }
RalewaySemiBold {
id: categoryLabel
anchors.top: parent.top
anchors.left: parent.left
width: paintedWidth
text: "IN:"
size: 14
color: hifi.colors.lightGrayText
verticalAlignment: Text.AlignVCenter
}
ListModel {
id: categoriesListModel
}
ListView {
anchors {
left: parent.left
right: parent.right
top: categoryLabel.bottom
bottomMargin: 15
}
height: 24*model.count+10
model: categoriesListModel
delegate: RalewaySemiBold {
id: categoryText
anchors.leftMargin: 15
width: paintedWidth
text: model.category
size: 14
height: 24
color: hifi.colors.blueHighlight
verticalAlignment: Text.AlignVCenter
MouseArea {
anchors.fill: categoryText
onClicked: root.categoryClicked(model.category);
}
}
}
}
}
}

View file

@ -0,0 +1,321 @@
//
// MarketplaceListItem.qml
// qml/hifi/commerce/marketplace
//
// MarketplaceListItem
//
// Created by Roxanne Skelly on 2019-01-22
// Copyright 2019 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import Hifi 1.0 as Hifi
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0
import stylesUit 1.0
import controlsUit 1.0 as HifiControlsUit
import "../../../controls" as HifiControls
import "../common" as HifiCommerceCommon
import "qrc:////qml//hifi//models" as HifiModels // Absolute path so the same code works everywhere.
import "../common/sendAsset"
import "../.." as HifiCommon
Rectangle {
id: root
property string item_id: ""
property string image_url: ""
property string name: ""
property int likes: 0
property bool liked: false
property string creator: ""
property string category: ""
property int price: 0
property bool available: false
property bool isLoggedIn: false;
signal buy()
signal showItem()
signal categoryClicked(string category)
signal requestReload()
HifiConstants { id: hifi }
width: parent.width
height: childrenRect.height+50
DropShadow {
anchors.fill: shadowBase
source: shadowBase
verticalOffset: 4
horizontalOffset: 4
radius: 6
samples: 9
color: hifi.colors.baseGrayShadow
}
Rectangle {
id: shadowBase
anchors.fill: itemRect
color: "white"
}
Rectangle {
id: itemRect
anchors {
left: parent.left
right: parent.right
top: parent.top
topMargin: 20
bottomMargin: 10
leftMargin: 15
rightMargin: 15
}
height: childrenRect.height
MouseArea {
anchors.fill: parent
hoverEnabled: true
onClicked: root.showItem();
onEntered: hoverRect.visible = true;
onExited: hoverRect.visible = false;
}
Rectangle {
id: header
anchors {
left: parent.left
right: parent.right
top: parent.top
}
height: 50
RalewaySemiBold {
id: nameText
anchors {
top: parent.top
left: parent.left
right: parent.right
rightMargin: 50
leftMargin: 15
bottom: parent.bottom
}
width: paintedWidth
text: root.name
size: hifi.fontSizes.overlayTitle
elide: Text.ElideRight
color: hifi.colors.blueHighlight
verticalAlignment: Text.AlignVCenter
}
Item {
id: likes
anchors {
top: parent.top
right: parent.right
rightMargin: 15
bottom: parent.bottom
}
width: heart.width + likesText.width
Connections {
target: MarketplaceScriptingInterface
onMarketplaceItemLikeResult: {
if (result.status !== 'success') {
console.log("Failed to get Marketplace Categories", result.data.message);
root.requestReload();
}
}
}
RalewaySemiBold {
id: heart
anchors {
top: parent.top
right: parent.right
rightMargin: 0
verticalCenter: parent.verticalCenter
}
text: "\u2665"
size: 20
horizontalAlignment: Text.AlignHCenter;
color: root.liked ? hifi.colors.redAccent : hifi.colors.lightGrayText
}
RalewaySemiBold {
id: likesText
anchors {
top: parent.top
right: heart.left
rightMargin: 5
leftMargin: 15
bottom: parent.bottom
}
width: paintedWidth
text: root.likes
size: hifi.fontSizes.overlayTitle
color: hifi.colors.baseGray
verticalAlignment: Text.AlignVCenter
}
MouseArea {
anchors {
left: likesText.left
right: heart.right
top: parent.top
bottom: parent.bottom
}
onClicked: {
if (isLoggedIn) {
root.liked = !root.liked;
root.likes = root.liked ? root.likes + 1 : root.likes - 1;
MarketplaceScriptingInterface.marketplaceItemLike(root.item_id, root.liked);
}
}
}
}
}
Image {
id: itemImage
anchors {
top: header.bottom
left: parent.left
right: parent.right
}
height: width * 0.5625
source: root.image_url
fillMode: Image.PreserveAspectCrop
}
Item {
id: footer
anchors {
left: parent.left
right: parent.right
top: itemImage.bottom
}
height: 60
RalewaySemiBold {
id: creatorLabel
anchors {
top: parent.top
left: parent.left
leftMargin: 15
}
width: paintedWidth
text: "CREATOR:"
size: 14
color: hifi.colors.lightGrayText
verticalAlignment: Text.AlignVCenter
}
RalewaySemiBold {
id: creatorText
anchors {
top: creatorLabel.top;
left: creatorLabel.right;
leftMargin: 15;
}
width: paintedWidth;
text: root.creator;
size: 14;
color: hifi.colors.lightGray;
verticalAlignment: Text.AlignVCenter;
}
RalewaySemiBold {
id: categoryLabel
anchors {
top: creatorLabel.bottom
left: parent.left
leftMargin: 15
}
width: paintedWidth;
text: "IN:";
size: 14;
color: hifi.colors.lightGrayText;
verticalAlignment: Text.AlignVCenter;
}
RalewaySemiBold {
id: categoryText
anchors {
top: categoryLabel.top
left: categoryLabel.right
leftMargin: 15
}
width: paintedWidth
text: root.category
size: 14
color: hifi.colors.blueHighlight;
verticalAlignment: Text.AlignVCenter;
MouseArea {
anchors.fill: parent
onClicked: root.categoryClicked(root.category);
}
}
HifiControlsUit.Button {
anchors {
right: parent.right
top: parent.top
bottom: parent.bottom
rightMargin: 15
topMargin:10
bottomMargin: 10
}
text: root.price ? root.price : "FREE"
buttonGlyph: root.price ? hifi.glyphs.hfc : ""
color: hifi.buttons.blue;
onClicked: root.buy();
}
}
Rectangle {
id: hoverRect
anchors.fill: parent
border.color: hifi.colors.blueHighlight
border.width: 2
color: "#00000000"
visible: false
}
}
}

View file

@ -0,0 +1,87 @@
//
// SortButton.qml
// qml/hifi/commerce/marketplace
//
// SortButton
//
// Created by Roxanne Skelly on 2019-01-18
// Copyright 2019 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import Hifi 1.0 as Hifi
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0
import stylesUit 1.0
import controlsUit 1.0 as HifiControlsUit
import "../../../controls" as HifiControls
import "../common" as HifiCommerceCommon
import "qrc:////qml//hifi//models" as HifiModels // Absolute path so the same code works everywhere.
import "../common/sendAsset"
import "../.." as HifiCommon
Item {
HifiConstants { id: hifi; }
id: root;
property string glyph: "";
property string text: "";
property bool checked: false;
signal clicked();
width: childrenRect.width;
height: parent.height;
Rectangle {
anchors.top: parent.top;
anchors.left: parent.left;
height: parent.height;
width: 2;
color: hifi.colors.faintGray;
visible: index > 0;
}
HiFiGlyphs {
id: buttonGlyph;
text: root.glyph;
// Size
size: 14;
// Anchors
anchors.left: parent.left;
anchors.leftMargin: 0;
anchors.top: parent.top;
anchors.verticalCenter: parent.verticalCenter;
height: parent.height;
horizontalAlignment: Text.AlignHCenter;
// Style
color: hifi.colors.lightGray;
}
RalewayRegular {
id: buttonText;
text: root.text;
// Text size
size: 14;
// Style
color: hifi.colors.lightGray;
elide: Text.ElideRight;
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
// Anchors
anchors.left: parent.left;
anchors.leftMargin: 20;
anchors.top: parent.top;
height: parent.height;
}
MouseArea {
anchors.fill: parent;
hoverEnabled: enabled;
onClicked: {
root.clicked();
}
}
}

View file

@ -28,6 +28,7 @@ Item {
property string purchaseStatus;
property string itemName;
property string itemId;
property string updateItemId;
property string itemPreviewImageUrl;
property string itemHref;
property string certificateId;
@ -45,9 +46,9 @@ Item {
property bool cardBackVisible;
property bool isInstalled;
property string wornEntityID;
property string upgradeUrl;
property string updatedItemId;
property string upgradeTitle;
property bool updateAvailable: root.upgradeUrl !== "";
property bool updateAvailable: root.updateItemId && root.updateItemId !== "";
property bool valid;
property string originalStatusText;
@ -175,7 +176,7 @@ Item {
Item {
property alias buttonGlyphText: buttonGlyph.text;
property alias buttonText: buttonText.text;
property alias itemButtonText: buttonText.text;
property alias glyphSize: buttonGlyph.size;
property string buttonColor: hifi.colors.black;
property string buttonColor_hover: hifi.colors.blueHighlight;
@ -243,7 +244,7 @@ Item {
onLoaded: {
item.enabled = root.valid;
item.buttonGlyphText = hifi.glyphs.gift;
item.buttonText = "Gift";
item.itemButtonText = "Gift";
item.buttonClicked = function() {
sendToPurchases({ method: 'flipCard', closeAll: true });
sendToPurchases({
@ -270,7 +271,7 @@ Item {
onLoaded: {
item.buttonGlyphText = hifi.glyphs.market;
item.buttonText = "View in Marketplace";
item.itemButtonText = "View in Marketplace";
item.buttonClicked = function() {
sendToPurchases({ method: 'flipCard', closeAll: true });
sendToPurchases({method: 'purchases_itemInfoClicked', itemId: root.itemId});
@ -288,7 +289,7 @@ Item {
onLoaded: {
item.buttonGlyphText = hifi.glyphs.certificate;
item.buttonText = "View Certificate";
item.itemButtonText = "View Certificate";
item.buttonClicked = function() {
sendToPurchases({ method: 'flipCard', closeAll: true });
sendToPurchases({method: 'purchases_itemCertificateClicked', itemCertificateId: root.certificateId});
@ -307,7 +308,7 @@ Item {
onLoaded: {
item.buttonGlyphText = hifi.glyphs.uninstall;
item.buttonText = "Uninstall";
item.itemButtonText = "Uninstall";
item.buttonClicked = function() {
sendToPurchases({ method: 'flipCard', closeAll: true });
Commerce.uninstallApp(root.itemHref);
@ -330,15 +331,14 @@ Item {
onLoaded: {
item.buttonGlyphText = hifi.glyphs.update;
item.buttonText = "Update";
item.itemButtonText = "Update";
item.buttonColor = "#E2334D";
item.buttonClicked = function() {
sendToPurchases({ method: 'flipCard', closeAll: true });
sendToPurchases({
method: 'updateItemClicked',
itemId: root.itemId,
itemId: root.updateAvailable ? root.updateItemId : root.itemId,
itemEdition: root.itemEdition,
upgradeUrl: root.upgradeUrl,
itemHref: root.itemHref,
itemType: root.itemType,
isInstalled: root.isInstalled,
@ -378,10 +378,10 @@ Item {
function updateProperties() {
if (updateButton.visible && uninstallButton.visible) {
item.buttonText = "";
item.itemButtonText = "";
item.glyphSize = 20;
} else {
item.buttonText = "Send to Trash";
item.itemButtonText = "Send to Trash";
item.glyphSize = 30;
}
}

View file

@ -29,7 +29,6 @@ Rectangle {
id: root;
property string activeView: "initialize";
property string referrerURL: "";
property bool securityImageResultReceived: false;
property bool purchasesReceived: false;
property bool punctuationMode: false;
@ -154,55 +153,10 @@ Rectangle {
}
}
//
// TITLE BAR START
//
HifiCommerceCommon.EmulatedMarketplaceHeader {
id: titleBarContainer;
z: 997;
visible: false;
height: 100;
// Size
width: parent.width;
// Anchors
anchors.left: parent.left;
anchors.top: parent.top;
Connections {
onSendToParent: {
if (msg.method === 'needsLogIn' && root.activeView !== "needsLogIn") {
root.activeView = "needsLogIn";
} else if (msg.method === 'showSecurityPicLightbox') {
lightboxPopup.titleText = "Your Security Pic";
lightboxPopup.bodyImageSource = msg.securityImageSource;
lightboxPopup.bodyText = lightboxPopup.securityPicBodyText;
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.visible = true;
} else {
sendToScript(msg);
}
}
}
}
MouseArea {
enabled: titleBarContainer.usernameDropdownVisible;
anchors.fill: parent;
onClicked: {
titleBarContainer.usernameDropdownVisible = false;
}
}
//
// TITLE BAR END
//
Rectangle {
id: initialize;
visible: root.activeView === "initialize";
anchors.top: titleBarContainer.bottom;
anchors.topMargin: -titleBarContainer.additionalDropdownHeight;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
@ -219,8 +173,7 @@ Rectangle {
id: installedAppsContainer;
z: 998;
visible: false;
anchors.top: titleBarContainer.bottom;
anchors.topMargin: -titleBarContainer.additionalDropdownHeight;
anchors.top: parent.top;
anchors.left: parent.left;
anchors.bottom: parent.bottom;
width: parent.width;
@ -422,8 +375,8 @@ Rectangle {
// Anchors
anchors.left: parent.left;
anchors.right: parent.right;
anchors.top: titleBarContainer.bottom;
anchors.topMargin: 8 - titleBarContainer.additionalDropdownHeight;
anchors.top: parent.top;
anchors.topMargin: 8;
anchors.bottom: parent.bottom;
//
@ -585,6 +538,7 @@ Rectangle {
delegate: PurchasedItem {
itemName: title;
itemId: id;
updateItemId: model.upgrade_id ? model.upgrade_id : "";
itemPreviewImageUrl: preview;
itemHref: download_url;
certificateId: certificate_id;
@ -596,7 +550,6 @@ Rectangle {
cardBackVisible: model.cardBackVisible || false;
isInstalled: model.isInstalled || false;
wornEntityID: model.wornEntityID;
upgradeUrl: model.upgrade_url;
upgradeTitle: model.upgrade_title;
itemType: model.item_type;
valid: model.valid;
@ -1083,8 +1036,6 @@ Rectangle {
function fromScript(message) {
switch (message.method) {
case 'updatePurchases':
referrerURL = message.referrerURL || "";
titleBarContainer.referrerURL = message.referrerURL || "";
filterBar.text = message.filterText ? message.filterText : "";
break;
case 'purchases_showMyItems':

View file

@ -335,7 +335,7 @@ Item {
if (link.indexOf("users/") !== -1) {
sendSignalToWallet({method: 'transactionHistory_usernameLinkClicked', usernameLink: link});
} else {
sendSignalToWallet({method: 'transactionHistory_linkClicked', marketplaceLink: link});
sendSignalToWallet({method: 'transactionHistory_linkClicked', itemId: model.marketplace_item});
}
}
}

View file

@ -235,6 +235,7 @@
#include "commerce/Ledger.h"
#include "commerce/Wallet.h"
#include "commerce/QmlCommerce.h"
#include "commerce/QmlMarketplace.h"
#include "ResourceRequestObserver.h"
#include "webbrowser/WebBrowserSuggestionsEngine.h"
@ -3008,7 +3009,23 @@ void Application::initializeUi() {
QUrl{ "hifi/dialogs/security/SecurityImageModel.qml" },
QUrl{ "hifi/dialogs/security/SecurityImageSelection.qml" },
QUrl{ "hifi/tablet/TabletMenu.qml" },
QUrl{ "hifi/commerce/marketplace/Marketplace.qml" },
}, commerceCallback);
QmlContextCallback marketplaceCallback = [](QQmlContext* context) {
context->setContextProperty("MarketplaceScriptingInterface", new QmlMarketplace());
};
OffscreenQmlSurface::addWhitelistContextHandler({
QUrl{ "hifi/commerce/marketplace/Marketplace.qml" },
}, marketplaceCallback);
QmlContextCallback platformInfoCallback = [](QQmlContext* context) {
context->setContextProperty("PlatformInfo", new PlatformInfoScriptingInterface());
};
OffscreenQmlSurface::addWhitelistContextHandler({
QUrl{ "hifi/commerce/marketplace/Marketplace.qml" },
}, platformInfoCallback);
QmlContextCallback ttsCallback = [](QQmlContext* context) {
context->setContextProperty("TextToSpeech", DependencyManager::get<TTSScriptingInterface>().data());
};

View file

@ -75,7 +75,6 @@ const float PITCH_SPEED_DEFAULT = 75.0f; // degrees/sec
const float MAX_BOOST_SPEED = 0.5f * DEFAULT_AVATAR_MAX_WALKING_SPEED; // action motor gets additive boost below this speed
const float MIN_AVATAR_SPEED = 0.05f;
const float MIN_AVATAR_SPEED_SQUARED = MIN_AVATAR_SPEED * MIN_AVATAR_SPEED; // speed is set to zero below this
float MIN_SCRIPTED_MOTOR_TIMESCALE = 0.005f;
float DEFAULT_SCRIPTED_MOTOR_TIMESCALE = 1.0e6f;
@ -847,6 +846,7 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
updateOrientation(deltaTime);
updatePosition(deltaTime);
updateViewBoom();
}
// update sensorToWorldMatrix for camera and hand controllers
@ -3323,21 +3323,22 @@ void MyAvatar::updateActionMotor(float deltaTime) {
direction = Vectors::ZERO;
}
float sensorToWorldScale = getSensorToWorldScale();
if (state == CharacterController::State::Hover) {
// we're flying --> complex acceleration curve that builds on top of current motor speed and caps at some max speed
float motorSpeed = glm::length(_actionMotorVelocity);
float finalMaxMotorSpeed = getSensorToWorldScale() * DEFAULT_AVATAR_MAX_FLYING_SPEED * _walkSpeedScalar;
float finalMaxMotorSpeed = sensorToWorldScale * DEFAULT_AVATAR_MAX_FLYING_SPEED * _walkSpeedScalar;
float speedGrowthTimescale = 2.0f;
float speedIncreaseFactor = 1.8f * _walkSpeedScalar;
motorSpeed *= 1.0f + glm::clamp(deltaTime / speedGrowthTimescale, 0.0f, 1.0f) * speedIncreaseFactor;
const float maxBoostSpeed = getSensorToWorldScale() * MAX_BOOST_SPEED;
const float maxBoostSpeed = sensorToWorldScale * MAX_BOOST_SPEED;
if (_isPushing) {
if (motorSpeed < maxBoostSpeed) {
// an active action motor should never be slower than this
float boostCoefficient = (maxBoostSpeed - motorSpeed) / maxBoostSpeed;
motorSpeed += getSensorToWorldScale() * MIN_AVATAR_SPEED * boostCoefficient;
motorSpeed += sensorToWorldScale * MIN_AVATAR_SPEED * boostCoefficient;
} else if (motorSpeed > finalMaxMotorSpeed) {
motorSpeed = finalMaxMotorSpeed;
}
@ -3348,45 +3349,21 @@ void MyAvatar::updateActionMotor(float deltaTime) {
const glm::vec2 currentVel = { direction.x, direction.z };
float scaledSpeed = scaleSpeedByDirection(currentVel, _walkSpeed.get(), _walkBackwardSpeed.get());
// _walkSpeedScalar is a multiplier if we are in sprint mode, otherwise 1.0
_actionMotorVelocity = getSensorToWorldScale() * (scaledSpeed * _walkSpeedScalar) * direction;
}
float previousBoomLength = _boomLength;
float boomChange = getDriveKey(ZOOM);
_boomLength += 2.0f * _boomLength * boomChange + boomChange * boomChange;
_boomLength = glm::clamp<float>(_boomLength, ZOOM_MIN, ZOOM_MAX);
// May need to change view if boom length has changed
if (previousBoomLength != _boomLength) {
qApp->changeViewAsNeeded(_boomLength);
_actionMotorVelocity = sensorToWorldScale * (scaledSpeed * _walkSpeedScalar) * direction;
}
}
void MyAvatar::updatePosition(float deltaTime) {
if (_motionBehaviors & AVATAR_MOTION_ACTION_MOTOR_ENABLED) {
updateActionMotor(deltaTime);
}
vec3 velocity = getWorldVelocity();
float sensorToWorldScale = getSensorToWorldScale();
float sensorToWorldScale2 = sensorToWorldScale * sensorToWorldScale;
const float MOVING_SPEED_THRESHOLD_SQUARED = 0.0001f; // 0.01 m/s
if (!_characterController.isEnabledAndReady()) {
// _characterController is not in physics simulation but it can still compute its target velocity
updateMotors();
_characterController.computeNewVelocity(deltaTime, velocity);
float speed2 = glm::length(velocity);
if (speed2 > sensorToWorldScale2 * MIN_AVATAR_SPEED_SQUARED) {
// update position ourselves
applyPositionDelta(deltaTime * velocity);
if (_characterController.isEnabledAndReady()) {
if (_motionBehaviors & AVATAR_MOTION_ACTION_MOTOR_ENABLED) {
updateActionMotor(deltaTime);
}
measureMotionDerivatives(deltaTime);
_moving = speed2 > sensorToWorldScale2 * MOVING_SPEED_THRESHOLD_SQUARED;
} else {
float sensorToWorldScale = getSensorToWorldScale();
float sensorToWorldScale2 = sensorToWorldScale * sensorToWorldScale;
vec3 velocity = getWorldVelocity();
float speed2 = glm::length2(velocity);
const float MOVING_SPEED_THRESHOLD_SQUARED = 0.0001f; // 0.01 m/s
_moving = speed2 > sensorToWorldScale2 * MOVING_SPEED_THRESHOLD_SQUARED;
if (_moving) {
// scan for walkability
glm::vec3 position = getWorldPosition();
@ -3398,6 +3375,18 @@ void MyAvatar::updatePosition(float deltaTime) {
}
}
void MyAvatar::updateViewBoom() {
float previousBoomLength = _boomLength;
float boomChange = getDriveKey(ZOOM);
_boomLength += 2.0f * _boomLength * boomChange + boomChange * boomChange;
_boomLength = glm::clamp<float>(_boomLength, ZOOM_MIN, ZOOM_MAX);
// May need to change view if boom length has changed
if (previousBoomLength != _boomLength) {
qApp->changeViewAsNeeded(_boomLength);
}
}
void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTime, float frequency) {
// COLLISION SOUND API in Audio has been removed
}

View file

@ -1732,6 +1732,7 @@ private:
void updateOrientation(float deltaTime);
void updateActionMotor(float deltaTime);
void updatePosition(float deltaTime);
void updateViewBoom();
void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency);
void initHeadBones();
void initAnimGraph();

View file

@ -54,11 +54,10 @@ void QmlCommerce::openSystemApp(const QString& appName) {
{"GOTO", "hifi/tablet/TabletAddressDialog.qml"},
{"PEOPLE", "hifi/Pal.qml"},
{"WALLET", "hifi/commerce/wallet/Wallet.qml"},
{"MARKET", "/marketplace.html"}
{"MARKET", "hifi/commerce/marketplace/Marketplace.qml"}
};
static const QMap<QString, QString> systemInject{
{"MARKET", "/scripts/system/html/js/marketplacesInject.js"}
};

View file

@ -0,0 +1,135 @@
//
// QmlMarketplace.cpp
// interface/src/commerce
//
// Guard for safe use of Marketplace by authorized QML.
//
// Created by Roxanne Skelly on 1/18/19.
// Copyright 2019 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "QmlMarketplace.h"
#include "CommerceLogging.h"
#include "Application.h"
#include "DependencyManager.h"
#include <Application.h>
#include <UserActivityLogger.h>
#include <ScriptEngines.h>
#include <ui/TabletScriptingInterface.h>
#include "scripting/HMDScriptingInterface.h"
#define ApiHandler(NAME) void QmlMarketplace::NAME##Success(QNetworkReply* reply) { emit NAME##Result(apiResponse(#NAME, reply)); }
#define FailHandler(NAME) void QmlMarketplace::NAME##Failure(QNetworkReply* reply) { emit NAME##Result(failResponse(#NAME, reply)); }
#define Handler(NAME) ApiHandler(NAME) FailHandler(NAME)
Handler(getMarketplaceItems)
Handler(getMarketplaceItem)
Handler(marketplaceItemLike)
Handler(getMarketplaceCategories)
QmlMarketplace::QmlMarketplace() {
}
void QmlMarketplace::openMarketplace(const QString& marketplaceItemId) {
auto tablet = dynamic_cast<TabletProxy*>(
DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system"));
tablet->loadQMLSource("hifi/commerce/marketplace/Marketplace.qml");
DependencyManager::get<HMDScriptingInterface>()->openTablet();
if (!marketplaceItemId.isEmpty()) {
tablet->sendToQml(QVariantMap({ { "method", "marketplace_openItem" }, { "itemId", marketplaceItemId } }));
}
}
void QmlMarketplace::getMarketplaceItems(
const QString& q,
const QString& view,
const QString& category,
const QString& adminFilter,
const QString& adminFilterCost,
const QString& sort,
const bool isFree,
const int& page,
const int& perPage) {
QString endpoint = "items";
QUrlQuery request;
request.addQueryItem("q", q);
request.addQueryItem("view", view);
request.addQueryItem("category", category);
request.addQueryItem("adminFilter", adminFilter);
request.addQueryItem("adminFilterCost", adminFilterCost);
request.addQueryItem("sort", sort);
if (isFree) {
request.addQueryItem("isFree", "true");
}
request.addQueryItem("page", QString::number(page));
request.addQueryItem("perPage", QString::number(perPage));
send(endpoint, "getMarketplaceItemsSuccess", "getMarketplaceItemsFailure", QNetworkAccessManager::GetOperation, AccountManagerAuth::Optional, request);
}
void QmlMarketplace::getMarketplaceItem(const QString& marketplaceItemId) {
QString endpoint = QString("items/") + marketplaceItemId;
QUrlQuery request;
send(endpoint, "getMarketplaceItemSuccess", "getMarketplaceItemFailure", QNetworkAccessManager::GetOperation, AccountManagerAuth::Optional, request);
}
void QmlMarketplace::marketplaceItemLike(const QString& marketplaceItemId, const bool like) {
QString endpoint = QString("items/") + marketplaceItemId + "/like";
QUrlQuery request;
send(endpoint, "marketplaceItemLikeSuccess", "marketplaceItemLikeFailure", like ? QNetworkAccessManager::PostOperation : QNetworkAccessManager::DeleteOperation, AccountManagerAuth::Required, request);
}
void QmlMarketplace::getMarketplaceCategories() {
QString endpoint = "categories";
QUrlQuery request;
send(endpoint, "getMarketplaceCategoriesSuccess", "getMarketplaceCategoriesFailure", QNetworkAccessManager::GetOperation, AccountManagerAuth::None, request);
}
void QmlMarketplace::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, const QUrlQuery & request) {
auto accountManager = DependencyManager::get<AccountManager>();
const QString URL = "/api/v1/marketplace/";
JSONCallbackParameters callbackParams(this, success, fail);
accountManager->sendRequest(URL + endpoint,
authType,
method,
callbackParams,
QByteArray(),
NULL,
QVariantMap(),
request);
}
QJsonObject QmlMarketplace::apiResponse(const QString& label, QNetworkReply* reply) {
QByteArray response = reply->readAll();
QJsonObject data = QJsonDocument::fromJson(response).object();
#if defined(DEV_BUILD) // Don't expose user's personal data in the wild. But during development this can be handy.
qInfo(commerce) << label << "response" << QJsonDocument(data).toJson(QJsonDocument::Compact);
#endif
return data;
}
// Non-200 responses are not json:
QJsonObject QmlMarketplace::failResponse(const QString& label, QNetworkReply* reply) {
QString response = reply->readAll();
qWarning(commerce) << "FAILED" << label << response;
// tempResult will be NULL if the response isn't valid JSON.
QJsonDocument tempResult = QJsonDocument::fromJson(response.toLocal8Bit());
if (tempResult.isNull()) {
QJsonObject result
{
{ "status", "fail" },
{ "message", response }
};
return result;
}
else {
return tempResult.object();
}
}

View file

@ -0,0 +1,68 @@
//
// QmlMarketplace.h
// interface/src/commerce
//
// Guard for safe use of Marketplace by authorized QML.
//
// Created by Roxanne Skelly on 1/18/19.
// Copyright 2019 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
#ifndef hifi_QmlMarketplace_h
#define hifi_QmlMarketplace_h
#include <QJsonObject>
#include <QPixmap>
#include <QtNetwork/QNetworkReply>
#include "AccountManager.h"
class QmlMarketplace : public QObject {
Q_OBJECT
public:
QmlMarketplace();
public slots:
void getMarketplaceItemsSuccess(QNetworkReply* reply);
void getMarketplaceItemsFailure(QNetworkReply* reply);
void getMarketplaceItemSuccess(QNetworkReply* reply);
void getMarketplaceItemFailure(QNetworkReply* reply);
void getMarketplaceCategoriesSuccess(QNetworkReply* reply);
void getMarketplaceCategoriesFailure(QNetworkReply* reply);
void marketplaceItemLikeSuccess(QNetworkReply* reply);
void marketplaceItemLikeFailure(QNetworkReply* reply);
protected:
Q_INVOKABLE void openMarketplace(const QString& marketplaceItemId = QString());
Q_INVOKABLE void getMarketplaceItems(
const QString& q = QString(),
const QString& view = QString(),
const QString& category = QString(),
const QString& adminFilter = QString("published"),
const QString& adminFilterCost = QString(),
const QString& sort = QString(),
const bool isFree = false,
const int& page = 1,
const int& perPage = 20);
Q_INVOKABLE void getMarketplaceItem(const QString& marketplaceItemId);
Q_INVOKABLE void marketplaceItemLike(const QString& marketplaceItemId, const bool like = true);
Q_INVOKABLE void getMarketplaceCategories();
signals:
void getMarketplaceItemsResult(QJsonObject result);
void getMarketplaceItemResult(QJsonObject result);
void getMarketplaceCategoriesResult(QJsonObject result);
void marketplaceItemLikeResult(QJsonObject result);
private:
void send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, const QUrlQuery & request);
QJsonObject apiResponse(const QString& label, QNetworkReply* reply);
QJsonObject failResponse(const QString& label, QNetworkReply* reply);
};
#endif // hifi_QmlMarketplace_h

View file

@ -133,3 +133,11 @@ bool PlatformInfoScriptingInterface::hasRiftControllers() {
bool PlatformInfoScriptingInterface::hasViveControllers() {
return qApp->hasViveControllers();
}
bool PlatformInfoScriptingInterface::has3DHTML() {
#if defined(Q_OS_ANDROID)
return false;
#else
return true;
#endif
}

View file

@ -65,6 +65,12 @@ public slots:
* @function Window.hasRift
* @returns {boolean} <code>true</code> if running on Windows, otherwise <code>false</code>.*/
bool hasViveControllers();
/**jsdoc
* Returns true if device supports 3d HTML
* @function Window.hasRift
* @returns {boolean} <code>true</code> if device supports 3d HTML, otherwise <code>false</code>.*/
bool has3DHTML();
};
#endif // hifi_PlatformInfoScriptingInterface_h

View file

@ -208,7 +208,7 @@ void AccountManager::setSessionID(const QUuid& sessionID) {
}
}
QNetworkRequest AccountManager::createRequest(QString path, AccountManagerAuth::Type authType) {
QNetworkRequest AccountManager::createRequest(QString path, AccountManagerAuth::Type authType, const QUrlQuery & query) {
QNetworkRequest networkRequest;
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, _userAgentGetter());
@ -227,6 +227,7 @@ QNetworkRequest AccountManager::createRequest(QString path, AccountManagerAuth::
} else {
requestURL.setPath("/" + path);
}
requestURL.setQuery(query);
if (authType != AccountManagerAuth::None ) {
if (hasValidAccessToken()) {
@ -263,13 +264,14 @@ void AccountManager::sendRequest(const QString& path,
Q_ARG(const JSONCallbackParameters&, callbackParams),
Q_ARG(const QByteArray&, dataByteArray),
Q_ARG(QHttpMultiPart*, dataMultiPart),
Q_ARG(QVariantMap, propertyMap));
Q_ARG(QVariantMap, propertyMap),
Q_ARG(QUrlQuery, query));
return;
}
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest = createRequest(path, authType);
QNetworkRequest networkRequest = createRequest(path, authType, query);
if (VERBOSE_HTTP_REQUEST_DEBUGGING) {
qCDebug(networking) << "Making a request to" << qPrintable(networkRequest.url().toString());

View file

@ -61,7 +61,7 @@ class AccountManager : public QObject, public Dependency {
public:
AccountManager(UserAgentGetter userAgentGetter = DEFAULT_USER_AGENT_GETTER);
QNetworkRequest createRequest(QString path, AccountManagerAuth::Type authType);
QNetworkRequest createRequest(QString path, AccountManagerAuth::Type authType, const QUrlQuery & query = QUrlQuery());
Q_INVOKABLE void sendRequest(const QString& path,
AccountManagerAuth::Type authType,
QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,

View file

@ -729,12 +729,6 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char *dataBytes, QVecto
uint16_t length;
memcpy(&length, dataBytes, sizeof(uint16_t));
dataBytes += sizeof(length);
// FIXME - this size check is wrong if we allow larger packets
if (length * sizeof(glm::vec3) > MAX_OCTREE_UNCOMRESSED_PACKET_SIZE) {
result.resize(0);
return sizeof(uint16_t);
}
result.resize(length);
memcpy(result.data(), dataBytes, length * sizeof(glm::vec3));
return sizeof(uint16_t) + length * sizeof(glm::vec3);
@ -744,14 +738,7 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char *dataBytes, QVecto
uint16_t length;
memcpy(&length, dataBytes, sizeof(uint16_t));
dataBytes += sizeof(length);
// FIXME - this size check is wrong if we allow larger packets
if (length * sizeof(glm::quat) > MAX_OCTREE_UNCOMRESSED_PACKET_SIZE) {
result.resize(0);
return sizeof(uint16_t);
}
result.resize(length);
const unsigned char *start = dataBytes;
for (int i = 0; i < length; i++) {
dataBytes += unpackOrientationQuatFromBytes(dataBytes, result[i]);
@ -764,12 +751,6 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVecto
uint16_t length;
memcpy(&length, dataBytes, sizeof(uint16_t));
dataBytes += sizeof(length);
// FIXME - this size check is wrong if we allow larger packets
if (length * sizeof(float) > MAX_OCTREE_UNCOMRESSED_PACKET_SIZE) {
result.resize(0);
return sizeof(uint16_t);
}
result.resize(length);
memcpy(result.data(), dataBytes, length * sizeof(float));
return sizeof(uint16_t) + length * sizeof(float);
@ -779,14 +760,7 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVecto
uint16_t length;
memcpy(&length, dataBytes, sizeof(uint16_t));
dataBytes += sizeof(length);
// FIXME - this size check is wrong if we allow larger packets
if (length / 8 > MAX_OCTREE_UNCOMRESSED_PACKET_SIZE) {
result.resize(0);
return sizeof(uint16_t);
}
result.resize(length);
int bit = 0;
unsigned char current = 0;
const unsigned char *start = dataBytes;
@ -797,7 +771,6 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVecto
result[i] = (bool)(current & (1 << bit));
bit = (bit + 1) % BITS_IN_BYTE;
}
return (dataBytes - start) + (int)sizeof(uint16_t);
}

View file

@ -11,6 +11,16 @@
#include "CrashHelpers.h"
#ifdef NDEBUG
// undefine NDEBUG so doAssert() works for all builds
#undef NDEBUG
#include <assert.h>
#define NDEBUG
#else
#include <assert.h>
#endif
namespace crash {
class B;
@ -34,6 +44,11 @@ A::~A() {
_b->virtualFunction();
}
// only use doAssert() for debug purposes
void doAssert(bool value) {
assert(value);
}
void pureVirtualCall() {
qCDebug(shared) << "About to make a pure virtual call";
B b;

View file

@ -18,6 +18,7 @@
namespace crash {
void doAssert(bool value); // works for Release
void pureVirtualCall();
void doubleFree();
void nullDeref();

View file

@ -38,7 +38,6 @@ LogHandler::LogHandler() {
}
LogHandler::~LogHandler() {
flushRepeatedMessages();
}
const char* stringForLogType(LogMsgType msgType) {

View file

@ -379,21 +379,16 @@ function deleteSendMoneyParticleEffect() {
function onUsernameChanged() {
}
var MARKETPLACES_INJECT_SCRIPT_URL = Script.resolvePath("../html/js/marketplacesInject.js");
var METAVERSE_SERVER_URL = Account.metaverseServerURL;
var MARKETPLACE_URL_INITIAL = MARKETPLACE_URL + "?"; // Append "?" to signal injected script that it's the initial page.
function openMarketplace(optionalItemOrUrl) {
// This is a bit of a kluge, but so is the whole file.
// If given a whole path, use it with no cta.
// If given an id, build the appropriate url and use the id as the cta.
// Otherwise, use home and 'marketplace cta'.
// AND... if call onMarketplaceOpen to setupWallet if we need to.
var url = optionalItemOrUrl || MARKETPLACE_URL_INITIAL;
// If optionalItemOrUrl contains the metaverse base, then it's a url, not an item id.
if (optionalItemOrUrl && optionalItemOrUrl.indexOf(METAVERSE_SERVER_URL) === -1) {
url = MARKETPLACE_URL + '/items/' + optionalItemOrUrl;
var MARKETPLACE_QML_PATH = "hifi/commerce/marketplace/Marketplace.qml";
function openMarketplace(optionalItem) {
ui.open(MARKETPLACE_QML_PATH);
if (optionalItem) {
ui.tablet.sendToQml({
method: 'updateMarketplaceQMLItem',
params: { itemId: optionalItem }
});
}
ui.open(url, MARKETPLACES_INJECT_SCRIPT_URL);
}
function setCertificateInfo(itemCertificateId) {
@ -425,10 +420,10 @@ function fromQml(message) {
case 'purchases':
case 'marketplace cta':
case 'mainPage':
ui.open(MARKETPLACE_URL, MARKETPLACES_INJECT_SCRIPT_URL);
openMarketplace();
break;
default: // User needs to return to an individual marketplace item URL
ui.open(MARKETPLACE_URL + '/items/' + message.referrer, MARKETPLACES_INJECT_SCRIPT_URL);
default:
openMarketplace();
break;
}
break;
@ -440,13 +435,13 @@ function fromQml(message) {
case 'maybeEnableHmdPreview':
break; // do nothing here, handled in marketplaces.js
case 'transactionHistory_linkClicked':
ui.open(message.marketplaceLink, MARKETPLACES_INJECT_SCRIPT_URL);
openMarketplace(message.itemId);
break;
case 'goToMarketplaceMainPage':
ui.open(MARKETPLACE_URL, MARKETPLACES_INJECT_SCRIPT_URL);
openMarketplace();
break;
case 'goToMarketplaceItemPage':
ui.open(MARKETPLACE_URL + '/items/' + message.itemId, MARKETPLACES_INJECT_SCRIPT_URL);
openMarketplace(message.itemId);
break;
case 'refreshConnections':
print('Refreshing Connections...');

View file

@ -19,6 +19,7 @@
var CLARA_IO_CANCEL_DOWNLOAD = "CLARA.IO CANCEL DOWNLOAD";
var CLARA_IO_CANCELLED_DOWNLOAD = "CLARA.IO CANCELLED DOWNLOAD";
var GOTO_DIRECTORY = "GOTO_DIRECTORY";
var GOTO_MARKETPLACE = "GOTO_MARKETPLACE";
var QUERY_CAN_WRITE_ASSETS = "QUERY_CAN_WRITE_ASSETS";
var CAN_WRITE_ASSETS = "CAN_WRITE_ASSETS";
var WARN_USER_NO_PERMISSIONS = "WARN_USER_NO_PERMISSIONS";
@ -72,7 +73,16 @@
// Footer actions.
$("#back-button").on("click", function () {
(document.referrer !== "") ? window.history.back() : window.location = (marketplaceBaseURL + "/marketplace?");
if (document.referrer !== "") {
window.history.back();
} else {
var params = { type: GOTO_MARKETPLACE };
var itemIdMatch = location.search.match(/itemId=([^&]*)/);
if (itemIdMatch && itemIdMatch.length === 2) {
params.itemId = itemIdMatch[1];
}
EventBridge.emitWebEvent(JSON.stringify(params));
}
});
$("#all-markets").on("click", function () {
EventBridge.emitWebEvent(JSON.stringify({
@ -93,7 +103,9 @@
window.location = "https://clara.io/library?gameCheck=true&public=true";
});
$('#exploreHifiMarketplace').on('click', function () {
window.location = marketplaceBaseURL + "/marketplace?";
EventBridge.emitWebEvent(JSON.stringify({
type: GOTO_MARKETPLACE
}));
});
}

View file

@ -1,8 +1,8 @@
//
// marketplace.js
//
// Created by Eric Levin on 8 Jan 2016
// Copyright 2016 High Fidelity, Inc.
// Created by Roxanne Skelly on 1/18/2019
// Copyright 2019 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -10,108 +10,27 @@
(function() { // BEGIN LOCAL_SCOPE
/* global WebTablet */
Script.include("../libraries/WebTablet.js");
var AppUi = Script.require('appUi');
var toolIconUrl = Script.resolvePath("../assets/images/tools/");
var BUTTON_NAME = "MARKET";
var MARKETPLACE_QML_SOURCE = "hifi/commerce/marketplace/Marketplace.qml";
var ui;
function startup() {
var MARKETPLACE_URL = Account.metaverseServerURL + "/marketplace";
var marketplaceWindow = new OverlayWebWindow({
title: "Marketplace",
source: "about:blank",
width: 900,
height: 700,
visible: false
});
var toolHeight = 50;
var toolWidth = 50;
var TOOLBAR_MARGIN_Y = 0;
var marketplaceVisible = false;
var marketplaceWebTablet;
// We persist avatarEntity data in the .ini file, and reconsistitute it on restart.
// To keep things consistent, we pickle the tablet data in Settings, and kill any existing such on restart and domain change.
var persistenceKey = "io.highfidelity.lastDomainTablet";
function shouldShowWebTablet() {
var rightPose = Controller.getPoseValue(Controller.Standard.RightHand);
var leftPose = Controller.getPoseValue(Controller.Standard.LeftHand);
var hasHydra = !!Controller.Hardware.Hydra;
return HMD.active && (leftPose.valid || rightPose.valid || hasHydra);
ui = new AppUi({
buttonName: BUTTON_NAME,
sortOrder: 10,
home: MARKETPLACE_QML_SOURCE
});
}
function showMarketplace(marketplaceID) {
var url = MARKETPLACE_URL;
if (marketplaceID) {
url = url + "/items/" + marketplaceID;
}
tablet.gotoWebScreen(url);
marketplaceVisible = true;
UserActivityLogger.openedMarketplace();
function shutdown() {
}
function hideTablet(tablet) {
if (!tablet) {
return;
}
updateButtonState(false);
tablet.unregister();
tablet.destroy();
marketplaceWebTablet = null;
Settings.setValue(persistenceKey, "");
}
function clearOldTablet() { // If there was a tablet from previous domain or session, kill it and let it be recreated
}
function hideMarketplace() {
if (marketplaceWindow.visible) {
marketplaceWindow.setVisible(false);
marketplaceWindow.setURL("about:blank");
} else if (marketplaceWebTablet) {
}
marketplaceVisible = false;
}
function toggleMarketplace() {
if (marketplaceVisible) {
hideMarketplace();
} else {
showMarketplace();
}
}
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
var browseExamplesButton = tablet.addButton({
icon: "icons/tablet-icons/market-i.svg",
text: "MARKET"
});
function updateButtonState(visible) {
}
function onMarketplaceWindowVisibilityChanged() {
updateButtonState(marketplaceWindow.visible);
marketplaceVisible = marketplaceWindow.visible;
}
function onClick() {
toggleMarketplace();
}
browseExamplesButton.clicked.connect(onClick);
marketplaceWindow.visibleChanged.connect(onMarketplaceWindowVisibilityChanged);
clearOldTablet(); // Run once at startup, in case there's anything laying around from a crash.
// We could also optionally do something like Window.domainChanged.connect(function () {Script.setTimeout(clearOldTablet, 2000)}),
// but the HUD version stays around, so lets do the same.
Script.scriptEnding.connect(function () {
browseExamplesButton.clicked.disconnect(onClick);
tablet.removeButton(browseExamplesButton);
marketplaceWindow.visibleChanged.disconnect(onMarketplaceWindowVisibilityChanged);
});
//
// Run the functions.
//
startup();
Script.scriptEnding.connect(shutdown);
}()); // END LOCAL_SCOPE

View file

@ -19,12 +19,14 @@ var selectionDisplay = null; // for gridTool.js to ignore
var AppUi = Script.require('appUi');
Script.include("/~/system/libraries/gridTool.js");
Script.include("/~/system/libraries/connectionUtils.js");
Script.include("/~/system/libraries/accountUtils.js");
var MARKETPLACE_CHECKOUT_QML_PATH = "hifi/commerce/checkout/Checkout.qml";
var MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH = "hifi/commerce/inspectionCertificate/InspectionCertificate.qml";
var MARKETPLACE_ITEM_TESTER_QML_PATH = "hifi/commerce/marketplaceItemTester/MarketplaceItemTester.qml";
var MARKETPLACE_PURCHASES_QML_PATH = "hifi/commerce/wallet/Wallet.qml"; // HRS FIXME "hifi/commerce/purchases/Purchases.qml";
var MARKETPLACE_WALLET_QML_PATH = "hifi/commerce/wallet/Wallet.qml";
var MARKETPLACE_QML_PATH = "hifi/commerce/marketplace/Marketplace.qml";
var MARKETPLACES_INJECT_SCRIPT_URL = Script.resolvePath("../html/js/marketplacesInject.js");
var MARKETPLACES_URL = Script.resolvePath("../html/marketplaces.html");
var METAVERSE_SERVER_URL = Account.metaverseServerURL;
@ -36,6 +38,7 @@ var CLARA_IO_STATUS = "CLARA.IO STATUS";
var CLARA_IO_CANCEL_DOWNLOAD = "CLARA.IO CANCEL DOWNLOAD";
var CLARA_IO_CANCELLED_DOWNLOAD = "CLARA.IO CANCELLED DOWNLOAD";
var GOTO_DIRECTORY = "GOTO_DIRECTORY";
var GOTO_MARKETPLACE = "GOTO_MARKETPLACE";
var QUERY_CAN_WRITE_ASSETS = "QUERY_CAN_WRITE_ASSETS";
var CAN_WRITE_ASSETS = "CAN_WRITE_ASSETS";
var WARN_USER_NO_PERMISSIONS = "WARN_USER_NO_PERMISSIONS";
@ -154,18 +157,14 @@ function onMarketplaceOpen(referrer) {
}
}
function openMarketplace(optionalItemOrUrl) {
// This is a bit of a kluge, but so is the whole file.
// If given a whole path, use it with no cta.
// If given an id, build the appropriate url and use the id as the cta.
// Otherwise, use home and 'marketplace cta'.
// AND... if call onMarketplaceOpen to setupWallet if we need to.
var url = optionalItemOrUrl || MARKETPLACE_URL_INITIAL;
// If optionalItemOrUrl contains the metaverse base, then it's a url, not an item id.
if (optionalItemOrUrl && optionalItemOrUrl.indexOf(METAVERSE_SERVER_URL) === -1) {
url = MARKETPLACE_URL + '/items/' + optionalItemOrUrl;
function openMarketplace(optionalItem, edition) {
ui.open(MARKETPLACE_QML_PATH);
if (optionalItem) {
ui.tablet.sendToQml({
method: 'updateMarketplaceQMLItem',
params: { itemId: optionalItem, edition: edition }
});
}
ui.open(url, MARKETPLACES_INJECT_SCRIPT_URL);
}
// Function Name: wireQmlEventBridge()
@ -439,7 +438,9 @@ var referrerURL; // Used for updating Purchases QML
var filterText; // Used for updating Purchases QML
function onWebEventReceived(message) {
message = JSON.parse(message);
if (message.type === GOTO_DIRECTORY) {
if (message.type === GOTO_MARKETPLACE) {
openMarketplace(message.itemId);
} else if (message.type === GOTO_DIRECTORY) {
// This is the chooser between marketplaces. Only OUR markteplace
// requires/makes-use-of wallet, so doesn't go through openMarketplace bottleneck.
ui.open(MARKETPLACES_URL, MARKETPLACES_INJECT_SCRIPT_URL);
@ -485,7 +486,6 @@ function onWebEventReceived(message) {
} else if (message.type === "WALLET_SETUP") {
setupWallet('marketplace cta');
} else if (message.type === "MY_ITEMS") {
referrerURL = MARKETPLACE_URL_INITIAL;
filterText = "";
ui.open(MARKETPLACE_PURCHASES_QML_PATH);
wireQmlEventBridge(true);
@ -546,11 +546,10 @@ var onQmlMessageReceived = function onQmlMessageReceived(message) {
openWallet();
break;
case 'checkout_cancelClicked':
openMarketplace(message.params);
openMarketplace(message.itemId);
break;
case 'header_goToPurchases':
case 'checkout_goToPurchases':
referrerURL = MARKETPLACE_URL_INITIAL;
filterText = message.filterText;
ui.open(MARKETPLACE_PURCHASES_QML_PATH);
break;
@ -560,6 +559,25 @@ var onQmlMessageReceived = function onQmlMessageReceived(message) {
case 'checkout_continue':
openMarketplace();
break;
case 'marketplace_checkout':
ui.open(MARKETPLACE_CHECKOUT_QML_PATH);
ui.tablet.sendToQml({
method: 'updateCheckoutQMLItemID',
params: message
});
break;
case 'marketplace_marketplaces':
// This is the chooser between marketplaces. Only OUR markteplace
// requires/makes-use-of wallet, so doesn't go through openMarketplace bottleneck.
var url = MARKETPLACES_URL;
if(message.itemId) {
url = url + "?itemId=" + message.itemId
}
ui.open(url, MARKETPLACES_INJECT_SCRIPT_URL);
break;
case 'marketplace_open_link':
ui.open(message.link);
break;
case 'checkout_rezClicked':
case 'purchases_rezClicked':
case 'tester_rezClicked':
@ -588,18 +606,18 @@ var onQmlMessageReceived = function onQmlMessageReceived(message) {
}
break;
case 'header_marketplaceImageClicked':
openMarketplace(message.referrerURL);
openMarketplace();
break;
case 'purchases_goToMarketplaceClicked':
openMarketplace();
break;
case 'updateItemClicked':
openMarketplace(message.upgradeUrl + "?edition=" + message.itemEdition);
openMarketplace(message.itemId, message.itemEdition);
break;
case 'passphrasePopup_cancelClicked':
case 'needsLogIn_cancelClicked':
// Should/must NOT check for wallet setup.
ui.open(MARKETPLACE_URL_INITIAL, MARKETPLACES_INJECT_SCRIPT_URL);
openMarketplace();
break;
case 'needsLogIn_loginClicked':
openLoginWindow();
@ -624,10 +642,10 @@ var onQmlMessageReceived = function onQmlMessageReceived(message) {
ContextOverlay.requestOwnershipVerification(message.entity);
break;
case 'inspectionCertificate_showInMarketplaceClicked':
openMarketplace(message.marketplaceUrl);
console.log("INSPECTION CERTIFICATE SHOW IN MARKETPLACE CLICKED: " + message.itemId);
openMarketplace(message.itemId);
break;
case 'header_myItemsClicked':
referrerURL = MARKETPLACE_URL_INITIAL;
filterText = "";
ui.open(MARKETPLACE_PURCHASES_QML_PATH);
wireQmlEventBridge(true);
@ -689,7 +707,7 @@ var onMarketplaceScreen = false;
var onWalletScreen = false;
var onTabletScreenChanged = function onTabletScreenChanged(type, url) {
ui.setCurrentVisibleScreenMetadata(type, url);
onMarketplaceScreen = type === "Web" && url.indexOf(MARKETPLACE_URL) !== -1;
onMarketplaceScreen = type === "QML" && url.indexOf(MARKETPLACE_QML_PATH) !== -1;
onInspectionCertificateScreen = type === "QML" && url.indexOf(MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH) !== -1;
var onWalletScreenNow = url.indexOf(MARKETPLACE_WALLET_QML_PATH) !== -1;
var onCommerceScreenNow = type === "QML" && (
@ -699,7 +717,9 @@ var onTabletScreenChanged = function onTabletScreenChanged(type, url) {
var onMarketplaceItemTesterScreenNow = (
url.indexOf(MARKETPLACE_ITEM_TESTER_QML_PATH) !== -1 ||
url === MARKETPLACE_ITEM_TESTER_QML_PATH);
var onMarketplaceScreenNow = (
url.indexOf(MARKETPLACE_QML_PATH) !== -1 ||
url === MARKETPLACE_QML_PATH);
if ((!onWalletScreenNow && onWalletScreen) ||
(!onCommerceScreenNow && onCommerceScreen) ||
(!onMarketplaceItemTesterScreenNow && onMarketplaceScreen)
@ -711,7 +731,7 @@ var onTabletScreenChanged = function onTabletScreenChanged(type, url) {
onCommerceScreen = onCommerceScreenNow;
onWalletScreen = onWalletScreenNow;
onMarketplaceItemTesterScreen = onMarketplaceItemTesterScreenNow;
wireQmlEventBridge(onCommerceScreen || onWalletScreen || onMarketplaceItemTesterScreen);
wireQmlEventBridge(onCommerceScreen || onWalletScreen || onMarketplaceItemTesterScreen || onMarketplaceScreenNow);
if (url === MARKETPLACE_PURCHASES_QML_PATH) {
// FIXME? Is there a race condition here in which the event
@ -734,11 +754,8 @@ var onTabletScreenChanged = function onTabletScreenChanged(type, url) {
Keyboard.raised = false;
}
if (type === "Web" && url.indexOf(MARKETPLACE_URL) !== -1) {
ContextOverlay.isInMarketplaceInspectionMode = true;
} else {
ContextOverlay.isInMarketplaceInspectionMode = false;
}
ContextOverlay.isInMarketplaceInspectionMode = false;
if (onInspectionCertificateScreen) {
setCertificateInfo(contextOverlayEntity);
@ -769,16 +786,13 @@ var onTabletScreenChanged = function onTabletScreenChanged(type, url) {
var BUTTON_NAME = "MARKET";
var MARKETPLACE_URL = METAVERSE_SERVER_URL + "/marketplace";
// Append "?" if necessary to signal injected script that it's the initial page.
var MARKETPLACE_URL_INITIAL = MARKETPLACE_URL + (MARKETPLACE_URL.indexOf("?") > -1 ? "" : "?");
var ui;
function startup() {
ui = new AppUi({
buttonName: BUTTON_NAME,
sortOrder: 9,
inject: MARKETPLACES_INJECT_SCRIPT_URL,
home: MARKETPLACE_URL_INITIAL,
home: MARKETPLACE_QML_PATH,
onScreenChanged: onTabletScreenChanged,
onMessage: onQmlMessageReceived
});