QML Marketplace

Checkpoint full functionality
This commit is contained in:
Roxanne Skelly 2019-01-24 17:20:42 -08:00
parent 8010d86210
commit c1ff51a02d
12 changed files with 1592 additions and 160 deletions

View file

@ -30,24 +30,72 @@ Rectangle {
property string activeView: "initialize";
property bool keyboardRaised: false;
property int category_index: -1;
property alias categoryChoices: categoriesModel;
property int currentSortIndex: 0;
property string sortString: "";
property string categoryString: "";
property string searchString: "";
anchors.fill: (typeof parent === undefined) ? undefined : parent;
function getMarketplaceItems() {
marketplaceItemView.visible = false;
itemsList.visible = true;
marketBrowseModel.getFirstPage();
}
Component.onDestruction: {
KeyboardScriptingInterface.raised = false;
}
Connections {
target: Marketplace;
target: MarketplaceScriptingInterface;
onGetMarketplaceCategoriesResult: {
if (result.status !== 'success') {
console.log("Failed to get Marketplace Categories", result.data.message);
} else {
}
categoriesModel.clear();
categoriesModel.append({
id: -1,
name: "Everything"
});
result.data.items.forEach(function(category) {
categoriesModel.append({
id: category.id,
name: category.name
});
});
}
getMarketplaceItems();
}
onGetMarketplaceItemsResult: {
marketBrowseModel.handlePage(result.status !== "success" && result.message, result);
}
onGetMarketplaceItemResult: {
if (result.status !== 'success') {
console.log("Failed to get Marketplace Item", result.data.message);
} else {
console.log(JSON.stringify(result.data));
marketplaceItem.item_id = result.data.id;
marketplaceItem.image_url = result.data.thumbnail_url;
marketplaceItem.name = result.data.title;
marketplaceItem.likes = result.data.likes;
marketplaceItem.liked = result.data.has_liked;
marketplaceItem.creator = result.data.creator;
marketplaceItem.categories = result.data.categories;
marketplaceItem.price = result.data.cost;
marketplaceItem.description = result.data.description;
marketplaceItem.attributions = result.data.attributions;
marketplaceItem.license = result.data.license;
marketplaceItem.available = result.data.availability == "available";
marketplaceItem.created_at = result.data.created_at;
console.log("HEIGHT: " + marketplaceItemContent.height);
marketplaceItemScrollView.contentHeight = marketplaceItemContent.height;
itemsList.visible = false;
marketplaceItemView.visible = true;
}
}
}
@ -60,15 +108,36 @@ Rectangle {
//
// HEADER BAR START
//
Item {
Rectangle {
id: headerShadowBase;
anchors.fill: header;
color: "white";
}
DropShadow {
anchors.fill: headerShadowBase;
source: headerShadowBase;
verticalOffset: 4;
horizontalOffset: 4;
radius: 6;
samples: 9;
color: hifi.colors.baseGrayShadow;
z:5;
}
Rectangle {
id: header;
visible: true;
width: parent.width;
anchors.left: parent.left;
anchors.top: parent.top;
anchors.right: parent.right;
Item {
anchors.topMargin: -1;
anchors.leftMargin: -1;
anchors.rightMargin: -1;
height: childrenRect.height+5;
z: 5;
Rectangle {
id: titleBarContainer;
visible: true;
// Size
@ -77,13 +146,14 @@ Rectangle {
// Anchors
anchors.left: parent.left;
anchors.top: parent.top;
// Wallet icon
// Marketplace icon
Image {
id: walletIcon;
id: marketplaceIcon;
source: "../../../../images/hifi-logo-blackish.svg";
height: 20
width: walletIcon.height;
width: marketplaceIcon.height;
anchors.left: parent.left;
anchors.leftMargin: 8;
anchors.verticalCenter: parent.verticalCenter;
@ -98,7 +168,7 @@ Rectangle {
size: hifi.fontSizes.overlayTitle;
// Anchors
anchors.top: parent.top;
anchors.left: walletIcon.right;
anchors.left: marketplaceIcon.right;
anchors.leftMargin: 6;
anchors.bottom: parent.bottom;
width: paintedWidth;
@ -109,9 +179,10 @@ Rectangle {
}
}
Item {
Rectangle {
id: searchBarContainer;
visible: true;
clip: false;
// Size
width: parent.width;
anchors.top: titleBarContainer.bottom;
@ -125,10 +196,10 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter;
height: 34;
width: categoriesText.width + 25;
color: "white";
color: hifi.colors.white;
radius: 4;
border.width: 1;
border.color: hifi.colors.lightGray;
border.color: hifi.colors.lightGrayText;
// Categories Text
@ -136,9 +207,9 @@ Rectangle {
id: categoriesText;
text: "Categories";
// Text size
size: 18;
size: 14;
// Style
color: hifi.colors.baseGray;
color: hifi.colors.lightGrayText;
elide: Text.ElideRight;
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
@ -166,6 +237,8 @@ Rectangle {
hoverEnabled: enabled;
onClicked: {
categoriesDropdown.visible = !categoriesDropdown.visible;
categoriesButton.color = categoriesDropdown.visible ? hifi.colors.lightGray : hifi.colors.white;
categoriesDropdown.forceActiveFocus();
}
onEntered: categoriesText.color = hifi.colors.baseGrayShadow;
onExited: categoriesText.color = hifi.colors.baseGray;
@ -173,77 +246,10 @@ Rectangle {
Component.onCompleted: {
console.log("Getting Marketplace Categories");
console.log(JSON.stringify(Marketplace));
Marketplace.getMarketplaceItems();
MarketplaceScriptingInterface.getMarketplaceCategories();
}
}
Rectangle {
id: categoriesContainer;
visible: true;
height: 50 * categoriesModel.count;
width: parent.width;
anchors.top: categoriesButton.bottom;
anchors.left: categoriesButton.left;
color: hifi.colors.white;
ListModel {
id: categoriesModel;
}
ListView {
id: dropdownListView;
interactive: false;
anchors.fill: parent;
model: categoriesModel;
delegate: Item {
width: parent.width;
height: 50;
Rectangle {
id: dropDownButton;
color: hifi.colors.white;
width: parent.width;
height: 50;
visible: true;
RalewaySemiBold {
id: dropDownButtonText;
text: model.displayName;
anchors.fill: parent;
anchors.topMargin: 2;
anchors.leftMargin: 12;
color: hifi.colors.baseGray;
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignVCenter;
size: 18;
}
MouseArea {
anchors.fill: parent;
hoverEnabled: true;
propagateComposedEvents: false;
onEntered: {
dropDownButton.color = hifi.colors.blueHighlight;
}
onExited: {
dropDownButton.color = hifi.colors.white;
}
onClicked: {
root.category_index = index;
dropdownContainer.visible = false;
}
}
}
Rectangle {
height: 2;
width: parent.width;
color: hifi.colors.lightGray;
visible: model.separator
}
}
}
}
// or
RalewayRegular {
id: orText;
@ -283,7 +289,6 @@ Rectangle {
font.family: "FiraSans Regular";
font.pixelSize: hifi.fontSizes.textFieldInput;
font.capitalization: Font.AllUppercase;
text: root.primaryFilter_displayName;
}
// workaround for https://bugreports.qt.io/browse/QTBUG-49297
@ -295,20 +300,22 @@ Rectangle {
// emit accepted signal manually
if (acceptableInput) {
root.accepted();
root.forceActiveFocus();
searchField.accepted();
searchField.forceActiveFocus();
}
break;
case Qt.Key_Backspace:
if (textField.text === "") {
if (searchField.text === "") {
primaryFilter_index = -1;
}
break;
}
}
onTextChanged: root.searchString = text;
onAccepted: {
root.forceActiveFocus();
root.searchString = searchField.text;
getMarketplaceItems();
searchField.forceActiveFocus();
}
onActiveFocusChanged: {
@ -320,17 +327,579 @@ Rectangle {
}
}
}
//
// HEADER BAR END
//
DropShadow {
anchors.fill: header;
horizontalOffset: 0;
verticalOffset: 4;
radius: 4.0;
samples: 9
color: Qt.rgba(0, 0, 0, 0.25);
source: header;
visible: header.visible;
//
// CATEGORIES LIST START
//
Item {
id: categoriesDropdown;
anchors.fill: parent;
visible: false;
z: 10;
MouseArea {
anchors.fill: parent;
propagateComposedEvents: true;
onClicked: {
categoriesDropdown.visible = false;
categoriesButton.color = hifi.colors.white;
}
}
Rectangle {
anchors.left: parent.left;
anchors.bottom: parent.bottom;
anchors.top: parent.top;
anchors.topMargin: 100;
width: parent.width/3;
color: hifi.colors.white;
ListModel {
id: categoriesModel;
}
ListView {
id: categoriesListView;
anchors.fill: parent;
anchors.rightMargin: 10;
width: parent.width;
clip: true;
model: categoriesModel;
delegate: ItemDelegate {
height: 34;
width: parent.width;
clip: true;
contentItem: Rectangle {
id: categoriesItem;
anchors.fill: parent;
color: hifi.colors.white;
visible: true;
RalewayRegular {
id: categoriesItemText;
text: model.name;
anchors.leftMargin: 15;
anchors.fill:parent;
color: ListView.isCurrentItem ? hifi.colors.lightBlueHighlight : hifi.colors.baseGray;
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignVCenter;
size: 14;
}
}
MouseArea {
anchors.fill: parent;
hoverEnabled: true;
propagateComposedEvents: false;
z: 10;
onEntered: {
categoriesItem.color = ListView.isCurrentItem ? hifi.colors.white : hifi.colors.lightBlueHighlight;
}
onExited: {
categoriesItem.color = ListView.isCurrentItem ? hifi.colors.lightBlueHighlight : hifi.colors.white;
}
onClicked: {
categoriesListView.currentIndex = index;
categoriesText.text = categoriesItemText.text;
categoriesDropdown.visible = false;
categoriesButton.color = hifi.colors.white;
root.categoryString = categoriesItemText.text;
getMarketplaceItems();
}
}
}
ScrollBar.vertical: ScrollBar {
parent: categoriesListView.parent;
anchors.top: categoriesListView.top;
anchors.bottom: categoriesListView.bottom;
anchors.left: categoriesListView.right;
contentItem.opacity: 1;
}
}
}
}
//
// CATEGORIES LIST END
//
//
// ITEMS LIST START
//
Item {
id: itemsList;
anchors.fill: parent;
anchors.topMargin: 100;
anchors.bottomMargin: 50;
visible: true;
HifiModels.PSFListModel {
id: marketBrowseModel;
itemsPerPage: 7;
listModelName: 'marketBrowse';
listView: marketBrowseList;
getPage: function () {
MarketplaceScriptingInterface.getMarketplaceItems(
root.searchString == "" ? undefined : root.searchString,
"",
root.categoryString.toLowerCase(),
"",
"",
root.sortString,
false,
marketBrowseModel.currentPageToRetrieve,
marketBrowseModel.itemsPerPage
);
}
processPage: function(data) {
console.log(JSON.stringify(data));
data.items.forEach(function (item) {
console.log(JSON.stringify(item));
});
return data.items;
}
}
ListView {
id: marketBrowseList;
model: marketBrowseModel;
// Anchors
anchors.fill: parent;
anchors.rightMargin: 10;
orientation: ListView.Vertical;
focus: true;
clip: true;
delegate: MarketplaceListItem {
item_id: model.id;
image_url:model.thumbnail_url;
name: model.title;
likes: model.likes;
liked: model.has_liked;
creator: model.creator;
category: model.primary_category;
price: model.cost;
available: model.availability == "available";
anchors.topMargin: 10;
Component.onCompleted: {
console.log("Rendering marketplace list item " + model.id);
console.log(marketBrowseModel.count);
}
onShowItem: {
MarketplaceScriptingInterface.getMarketplaceItem(item_id);
}
onBuy: {
sendToScript({method: 'marketplace_checkout', itemId: item_id});
}
onCategoryClicked: {
root.categoryString = category;
categoriesText.text = category;
getMarketplaceItems();
}
onRequestReload: getMarketplaceItems();
}
ScrollBar.vertical: ScrollBar {
parent: marketBrowseList.parent;
anchors.top: marketBrowseList.top;
anchors.bottom: marketBrowseList.bottom;
anchors.left: marketBrowseList.right;
contentItem.opacity: 1;
}
headerPositioning: ListView.InlineHeader;
header: Item {
id: itemsHeading;
height: childrenRect.height;
width: parent.width;
Item {
id: breadcrumbs;
anchors.left: parent.left;
anchors.right: parent.right;
height: 34;
visible: categoriesListView.currentIndex >= 0;
RalewayRegular {
id: categoriesItemText;
text: "Home /";
anchors.leftMargin: 15;
anchors.fill:parent;
color: hifi.colors.blueHighlight;
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignVCenter;
size: 18;
}
MouseArea {
anchors.fill: parent;
onClicked: {
categoriesListView.currentIndex = -1;
categoriesText.text = "Categories";
root.categoryString = "";
getMarketplaceItems();
}
}
}
Item {
id: searchScope;
anchors.top: breadcrumbs.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
height: 50;
RalewaySemiBold {
id: searchScopeText;
text: "Featured";
anchors.leftMargin: 15;
anchors.fill:parent;
anchors.topMargin: 10;
color: hifi.colors.baseGray;
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignVCenter;
size: 22;
}
}
Item {
id: sort;
anchors.top: searchScope.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.topMargin: 10;
anchors.leftMargin: 15;
height: childrenRect.height;
RalewayRegular {
id: sortText;
text: "Sort:";
anchors.leftMargin: 15;
anchors.rightMargin: 20;
height: 34;
color: hifi.colors.lightGrayText;
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignVCenter;
size: 14;
}
Rectangle {
radius: 4;
border.width: 1;
border.color: hifi.colors.faintGray;
anchors.left: sortText.right;
anchors.top: parent.top;
width: 322;
height: 36;
anchors.leftMargin: 20;
ListModel {
id: sortModel;
ListElement {
name: "Name";
glyph: ";";
sortString: "alpha";
}
ListElement {
name: "Date";
glyph: ";";
sortString: "recent";
}
ListElement {
name: "Popular";
glyph: ";";
sortString: "likes";
}
ListElement {
name: "My Likes";
glyph: ";";
sortString: "my_likes";
}
}
ListView {
id: sortListView;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.left: parent.left;
anchors.topMargin:1;
anchors.bottomMargin:1;
anchors.leftMargin:1;
anchors.rightMargin:1;
width: childrenRect.width;
height: 34;
orientation: ListView.Horizontal;
focus: true;
clip: true;
highlightFollowsCurrentItem: false;
delegate: SortButton {
width: 80;
height: parent.height;
glyph: model.glyph;
text: model.name;
checked: {
ListView.isCurrentItem;
}
onClicked: {
root.currentSortIndex = index;
sortListView.positionViewAtIndex(index, ListView.Beginning);
sortListView.currentIndex = index;
root.sortString = model.sortString;
getMarketplaceItems();
}
}
highlight: Rectangle {
width: 80;
height: parent.height;
color: hifi.colors.faintGray;
x: sortListView.currentItem.x;
}
model: sortModel;
}
}
}
}
}
}
//
// ITEMS LIST END
//
//
// ITEM START
//
Item {
id: marketplaceItemView;
anchors.fill: parent;
width: parent.width;
anchors.topMargin: 120;
visible: false;
ScrollView {
id: marketplaceItemScrollView;
anchors.fill: parent;
clip: true;
ScrollBar.vertical.policy: ScrollBar.AlwaysOn;
contentWidth: parent.width;
Rectangle {
id: marketplaceItemContent;
width: parent.width;
height: childrenRect.height + 100;
// Title Bar text
RalewaySemiBold {
id: backText;
text: "Back";
// Text size
size: hifi.fontSizes.overlayTitle;
// Anchors
anchors.top: parent.top;
anchors.left: parent.left
anchors.leftMargin: 15;
anchors.bottomMargin: 10;
width: paintedWidth;
height: paintedHeight;
// Style
color: hifi.colors.blueHighlight;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
MouseArea {
anchors.fill: backText;
onClicked: {
getMarketplaceItems();
}
}
MarketplaceItem {
id: marketplaceItem;
anchors.top: backText.bottom;
width: parent.width;
height: childrenRect.height;
anchors.topMargin: 15;
onBuy: {
sendToScript({method: 'marketplace_checkout', itemId: item_id});
}
onShowLicense: {
licenseInfoWebView.url = url;
licenseInfo.visible = true;
}
onCategoryClicked: {
root.categoryString = category;
categoriesText.text = category;
getMarketplaceItems();
}
}
}
}
}
//
// ITEM END
//
//
// FOOTER START
//
Rectangle {
id: footer;
anchors.bottom: parent.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
height: 50;
color: hifi.colors.blueHighlight;
Item {
anchors.fill: parent;
anchors.rightMargin: 15;
anchors.leftMargin: 15;
HiFiGlyphs {
id: footerGlyph;
text: hifi.glyphs.info;
// Size
size: 34;
// Anchors
anchors.left: parent.left;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.rightMargin: 10;
// Style
color: hifi.colors.white;
// Alignment
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
}
RalewaySemiBold {
id: footerInfo;
text: "Get items from Clara.io!";
anchors.left: footerGlyph.right;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
color: hifi.colors.white;
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignVCenter;
size: 18;
}
HifiControlsUit.Button {
text: "SEE ALL MARKETS";
anchors.right: parent.right;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.topMargin: 10;
anchors.bottomMargin: 10;
anchors.leftMargin: 10;
anchors.rightMargin: 10;
width: 180;
onClicked: {
sendToScript({method: 'marketplace_marketplaces'});
}
}
}
}
//
// FOOTER END
//
//
// LICENSE START
//
Rectangle {
id: licenseInfo;
anchors.fill: root;
anchors.topMargin: 100;
anchors.bottomMargin: 0;
visible: false;
HifiControlsUit.WebView {
id: licenseInfoWebView;
anchors.bottomMargin: 1;
anchors.topMargin: 50;
anchors.leftMargin: 1;
anchors.rightMargin: 1;
anchors.fill: parent;
}
Item {
id: licenseClose;
anchors.top: parent.top;
anchors.right: parent.right;
anchors.topMargin: 10;
anchors.rightMargin: 10;
width: 30;
height: 30;
HiFiGlyphs {
anchors.fill: parent;
height: 30;
text: hifi.glyphs.close;
// Size
size: 34;
// Anchors
anchors.rightMargin: 0;
anchors.verticalCenter: parent.verticalCenter;
horizontalAlignment: Text.AlignHCenter;
// Style
color: hifi.colors.baseGray;
}
MouseArea {
anchors.fill: licenseClose;
onClicked: licenseInfo.visible = false;
}
}
}
//
// LICENSE END
//
//
// Function Name: fromScript()
//
// Relevant Variables:
// None
//
// Arguments:
// message: The message sent from the JavaScript, in this case the Marketplaces JavaScript.
// Messages are in format "{method, params}", like json-rpc.
//
// Description:
// Called when a message is received from a script.
//
function fromScript(message) {
console.log("FROM SCRIPT " + JSON.stringify(message));
switch (message.method) {
case 'updateMarketplaceQMLItem':
if (!message.params.itemId) {
console.log("A message with method 'updateMarketplaceQMLItem' was sent without an itemId!");
return;
}
MarketplaceScriptingInterface.getMarketplaceItem(message.params.itemId);
break;
}
}
}

View file

@ -0,0 +1,473 @@
//
// 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 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: "";
onCategoriesChanged: {
categoriesListModel.clear();
categories.forEach(function(category) {
console.log("category is " + category);
categoriesListModel.append({"category":category});
});
}
signal buy();
signal categoryClicked(string category);
signal showLicense(string url);
HifiConstants { id: hifi; }
Connections {
target: MarketplaceScriptingInterface;
onMarketplaceItemLikeResult: {
if (result.status !== 'success') {
console.log("Failed to get Marketplace Categories", 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;
}
anchors.left: parent.left;
anchors.right: parent.right;
anchors.leftMargin: 15;
anchors.rightMargin: 15;
height: childrenRect.height;
Rectangle {
id: header;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.top: parent.top;
height: 50;
RalewaySemiBold {
id: nameText;
text: root.name;
// Text size
size: 24;
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
anchors.bottom: parent.bottom;
width: paintedWidth;
// Style
color: hifi.colors.baseGray;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
Item {
id: likes;
anchors.top: parent.top;
anchors.right: parent.right;
anchors.bottom: parent.bottom;
anchors.rightMargin: 5;
RalewaySemiBold {
id: heart;
text: "\u2665";
// Size
size: 20;
// Anchors
anchors.top: parent.top;
anchors.right: parent.right;
anchors.rightMargin: 0;
anchors.verticalCenter: parent.verticalCenter;
horizontalAlignment: Text.AlignHCenter;
// Style
color: root.liked ? hifi.colors.redAccent : hifi.colors.lightGrayText;
}
RalewaySemiBold {
id: likesText;
text: root.likes;
// Text size
size: hifi.fontSizes.overlayTitle;
// Anchors
anchors.top: parent.top;
anchors.right: heart.left;
anchors.rightMargin: 5;
anchors.leftMargin: 15;
anchors.bottom: parent.bottom;
width: paintedWidth;
// Style
color: hifi.colors.baseGray;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
MouseArea {
anchors.left: likesText.left;
anchors.right: heart.right;
anchors.top: likesText.top;
anchors.bottom: likesText.bottom;
onClicked: {
MarketplaceScriptingInterface.marketplaceItemLike(root.item_id, !root.liked);
}
}
}
}
Image {
id: itemImage;
source: root.image_url;
anchors.top: header.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
height: width*0.5625
fillMode: Image.PreserveAspectCrop;
}
Item {
id: footer;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.top: itemImage.bottom;
height: childrenRect.height;
HifiControlsUit.Button {
id: buyButton;
text: root.available ? (root.price ? root.price : "FREE") : "UNAVAILABLE (not for sale)";
enabled: root.available;
buttonGlyph: root.available ? (root.price ? hifi.glyphs.hfc : "") : "";
anchors.right: parent.right;
anchors.top: parent.top;
anchors.left: parent.left;
anchors.topMargin: 15;
height: 50;
color: hifi.buttons.blue;
onClicked: root.buy();
}
Item {
id: creatorItem;
anchors.top: buyButton.bottom;
anchors.leftMargin: 15;
anchors.topMargin: 15;
width: parent.width;
height: childrenRect.height;
RalewaySemiBold {
id: creatorLabel;
text: "CREATOR:";
// Text size
size: 14;
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
width: paintedWidth;
// Style
color: hifi.colors.lightGrayText;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
RalewaySemiBold {
id: creatorText;
text: root.creator;
// Text size
size: 18;
// Anchors
anchors.top: creatorLabel.bottom;
anchors.left: parent.left;
anchors.topMargin: 10;
width: paintedWidth;
// Style
color: hifi.colors.blueHighlight;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
}
Item {
id: posted;
anchors.top: creatorItem.bottom;
anchors.leftMargin: 15;
anchors.topMargin: 15;
width: parent.width;
height: childrenRect.height;
RalewaySemiBold {
id: postedLabel;
text: "POSTED:";
// Text size
size: 14;
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
width: paintedWidth;
// Style
color: hifi.colors.lightGrayText;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
RalewaySemiBold {
id: created_at;
text: { getFormattedDate(root.created_at); }
// Text size
size: 14;
// Anchors
anchors.top: postedLabel.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.topMargin: 10;
// Style
color: hifi.colors.lightGray;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
}
Rectangle {
anchors.top: posted.bottom;
anchors.leftMargin: 15;
anchors.topMargin: 15;
width: parent.width;
height: 1;
color: hifi.colors.lightGray;
}
Item {
id: licenseItem;
anchors.top: posted.bottom;
anchors.left: parent.left;
anchors.topMargin: 30;
width: parent.width;
height: childrenRect.height;
RalewaySemiBold {
id: licenseLabel;
text: "SHARED UNDER:";
// Text size
size: 14;
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
width: paintedWidth;
// Style
color: hifi.colors.lightGrayText;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
RalewaySemiBold {
id: licenseText;
text: root.license;
// Text size
size: 14;
// Anchors
anchors.top: licenseLabel.bottom;
anchors.left: parent.left;
width: paintedWidth;
// Style
color: hifi.colors.lightGray;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
RalewaySemiBold {
id: licenseHelp;
text: "More about this license";
// Text size
size: 14;
// Anchors
anchors.top: licenseText.bottom;
anchors.left: parent.left;
width: paintedWidth;
// Style
color: hifi.colors.blueHighlight;
// Alignment
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/"
} else if (root.license == "Attribution-ShareAlike (CC BY-SA)") {
url = "https://creativecommons.org/licenses/by-sa/4.0/"
} else if (root.license == "Attribution-NoDerivs (CC BY-ND)") {
url = "https://creativecommons.org/licenses/by-nd/4.0/"
} else if (root.license == "Attribution-NonCommercial (CC BY-NC)") {
url = "https://creativecommons.org/licenses/by-nc/4.0/"
} else if (root.license == "Attribution-NonCommercial-ShareAlike (CC BY-NC-SA)") {
url = "https://creativecommons.org/licenses/by-nc-sa/4.0/"
} else if (root.license == "Attribution-NonCommercial-NoDerivs (CC BY-NC-ND)") {
url = "https://creativecommons.org/licenses/by-nc-nd/4.0/"
} else if (root.license == "Proof of Provenance License (PoP License)") {
url = "https://digitalassetregistry.com/PoP-License/v1/"
}
if(url) {
licenseInfoWebView.url = url;
}
}
}
}
}
Item {
id: descriptionItem;
anchors.top: licenseItem.bottom;
anchors.topMargin: 15;
anchors.left: parent.left;
anchors.right: parent.right;
height: childrenRect.height;
RalewaySemiBold {
id: descriptionLabel;
text: "DESCRIPTION:";
// Text size
size: 14;
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
width: paintedWidth;
// Style
color: hifi.colors.lightGrayText;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
RalewaySemiBold {
id: descriptionText;
text: root.description;
// Text size
size: 14;
// Anchors
anchors.top: descriptionLabel.bottom;
anchors.left: parent.left;
width: parent.width;
// Style
color: hifi.colors.lightGray;
// Alignment
verticalAlignment: Text.AlignVCenter;
wrapMode: Text.Wrap;
}
}
Item {
id: categoriesList;
anchors.top: descriptionItem.bottom;
anchors.topMargin: 15;
anchors.left: parent.left;
anchors.right: parent.right;
width: parent.width;
height: childrenRect.height;
RalewaySemiBold {
id: categoryLabel;
text: "IN:";
// Text size
size: 14;
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
width: paintedWidth;
// Style
color: hifi.colors.lightGrayText;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
ListModel {
id: categoriesListModel;
}
ListView {
anchors.left: parent.left;
anchors.right: parent.right;
anchors.top: categoryLabel.bottom;
model: categoriesListModel;
height: 20*model.count;
delegate: RalewaySemiBold {
id: categoryText;
text: model.category;
// Text size
size: 14;
// Anchors
anchors.leftMargin: 15;
width: paintedWidth;
height: 20;
// Style
color: hifi.colors.blueHighlight;
// Alignment
verticalAlignment: Text.AlignVCenter;
MouseArea {
anchors.fill: categoryText;
onClicked: root.categoryClicked(model.category);
}
}
}
}
}
}

View file

@ -0,0 +1,278 @@
//
// 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;
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;
height: childrenRect.height;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.top: parent.top;
anchors.topMargin: 20;
anchors.bottomMargin: 10;
anchors.leftMargin: 15;
anchors.rightMargin: 15;
MouseArea {
anchors.fill: parent;
onClicked: root.showItem();
onEntered: { hoverRect.visible = true; console.log("entered"); }
onExited: { hoverRect.visible = false; console.log("exited"); }
hoverEnabled: true
}
Rectangle {
id: header;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.top: parent.top;
height: 50;
RalewaySemiBold {
id: nameText;
text: root.name;
// Text size
size: hifi.fontSizes.overlayTitle;
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.rightMargin: 50;
anchors.leftMargin: 15;
anchors.bottom: parent.bottom;
elide: Text.ElideRight;
width: paintedWidth;
// Style
color: hifi.colors.blueHighlight;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
Item {
id: likes;
anchors.top: parent.top;
anchors.right: parent.right;
anchors.rightMargin: 15;
anchors.bottom: parent.bottom;
width: childrenRect.width;
Connections {
target: MarketplaceScriptingInterface;
onMarketplaceItemLikeResult: {
if (result.status !== 'success') {
console.log("Failed to get Marketplace Categories", result.data.message);
root.requestReload();
}
}
}
RalewaySemiBold {
id: heart;
text: "\u2665";
// Size
size: 20;
// Anchors
anchors.top: parent.top;
anchors.right: parent.right;
anchors.rightMargin: 0;
anchors.verticalCenter: parent.verticalCenter;
horizontalAlignment: Text.AlignHCenter;
// Style
color: root.liked ? hifi.colors.redAccent : hifi.colors.lightGrayText;
}
RalewaySemiBold {
id: likesText;
text: root.likes;
// Text size
size: hifi.fontSizes.overlayTitle;
// Anchors
anchors.top: parent.top;
anchors.right: heart.left;
anchors.rightMargin: 5;
anchors.leftMargin: 15;
anchors.bottom: parent.bottom;
width: paintedWidth;
// Style
color: hifi.colors.baseGray;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
MouseArea {
anchors.fill: parent;
onClicked: {
console.log("like " + root.item_id);
root.liked = !root.liked;
root.likes = root.liked ? root.likes + 1 : root.likes - 1;
MarketplaceScriptingInterface.marketplaceItemLike(root.item_id, root.liked);
}
}
}
}
Image {
id: itemImage;
source: root.image_url;
anchors.top: header.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
height: width*0.5625
fillMode: Image.PreserveAspectCrop;
}
Item {
id: footer;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.top: itemImage.bottom;
height: 60;
RalewaySemiBold {
id: creatorLabel;
text: "CREATOR:";
// Text size
size: 14;
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
anchors.leftMargin: 15;
width: paintedWidth;
// Style
color: hifi.colors.lightGrayText;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
RalewaySemiBold {
id: creatorText;
text: root.creator;
// Text size
size: 14;
// Anchors
anchors.top: creatorLabel.top;
anchors.left: creatorLabel.right;
anchors.leftMargin: 15;
width: paintedWidth;
// Style
color: hifi.colors.lightGray;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
RalewaySemiBold {
id: categoryLabel;
text: "IN:";
// Text size
size: 14;
// Anchors
anchors.top: creatorLabel.bottom;
anchors.left: parent.left;
anchors.leftMargin: 15;
width: paintedWidth;
// Style
color: hifi.colors.lightGrayText;
// Alignment
verticalAlignment: Text.AlignVCenter;
}
RalewaySemiBold {
id: categoryText;
text: root.category;
// Text size
size: 14;
// Anchors
anchors.top: categoryLabel.top;
anchors.left: categoryLabel.right;
anchors.leftMargin: 15;
width: paintedWidth;
// Style
color: hifi.colors.blueHighlight;
// Alignment
verticalAlignment: Text.AlignVCenter;
MouseArea {
anchors.fill: parent;
onClicked: root.categoryClicked(root.category);
}
}
HifiControlsUit.Button {
text: root.price ? root.price : "FREE";
buttonGlyph: root.price ? hifi.glyphs.hfc : "";
anchors.right: parent.right;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.rightMargin: 15;
anchors.topMargin:10;
anchors.bottomMargin: 10;
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

@ -2916,7 +2916,7 @@ void Application::initializeUi() {
}, commerceCallback);
QmlContextCallback marketplaceCallback = [](QQmlContext* context) {
context->setContextProperty("Marketplace", new QmlMarketplace());
context->setContextProperty("MarketplaceScriptingInterface", new QmlMarketplace());
};
OffscreenQmlSurface::addWhitelistContextHandler({
QUrl{ "hifi/commerce/marketplace/Marketplace.qml" },

View file

@ -55,50 +55,54 @@ void QmlMarketplace::getMarketplaceItems(
const int& perPage) {
QString endpoint = "items";
QJsonObject request;
request["q"] = q;
request["view"] = view;
request["category"] = category;
request["adminFilter"] = adminFilter;
request["adminFilterCost"] = adminFilterCost;
request["sort"] = sort;
request["isFree"] = isFree;
request["page"] = page;
request["perPage"] = perPage;
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;
QJsonObject request;
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";
QJsonObject request;
send(endpoint, "marketplaceItemLikeSuccess", "marketplaceItemLikeFailure", like ? QNetworkAccessManager::PutOperation : QNetworkAccessManager::DeleteOperation, AccountManagerAuth::Required, request);
QUrlQuery request;
send(endpoint, "marketplaceItemLikeSuccess", "marketplaceItemLikeFailure", like ? QNetworkAccessManager::PostOperation : QNetworkAccessManager::DeleteOperation, AccountManagerAuth::Required, request);
}
void QmlMarketplace::getMarketplaceCategories() {
QString endpoint = "categories";
QJsonObject request;
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, QJsonObject 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);
#if defined(DEV_BUILD) // Don't expose user's personal data in the wild. But during development this can be handy.
qCInfo(commerce) << "Sending" << QJsonDocument(request).toJson(QJsonDocument::Compact);
#endif
accountManager->sendRequest(URL + endpoint,
authType,
method,
callbackParams,
QJsonDocument(request).toJson());
QByteArray(),
NULL,
QVariantMap(),
request);
}
QJsonObject QmlMarketplace::apiResponse(const QString& label, QNetworkReply* reply) {

View file

@ -60,7 +60,7 @@ signals:
void marketplaceItemLikeResult(QJsonObject result);
private:
void send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request);
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);
};

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

@ -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) {

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,13 @@
// Footer actions.
$("#back-button").on("click", function () {
(document.referrer !== "") ? window.history.back() : window.location = (marketplaceBaseURL + "/marketplace?");
if (document.referrer !== "") {
window.history.back();
} else {
EventBridge.emitWebEvent(JSON.stringify({
type: GOTO_MARKETPLACE
}));
}
});
$("#all-markets").on("click", function () {
EventBridge.emitWebEvent(JSON.stringify({
@ -93,7 +100,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

@ -25,6 +25,7 @@ var MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH = "hifi/commerce/inspectionCertif
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 +37,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 +156,15 @@ 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) {
ui.open(MARKETPLACE_QML_PATH);
if (optionalItem) {
ui.tablet.sendToQml({
method: 'updateMarketplaceQMLItem',
params: { itemId: optionalItem }
});
}
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();
} 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);
@ -518,6 +519,7 @@ var onQmlMessageReceived = function onQmlMessageReceived(message) {
if (message.messageSrc === "HTML") {
return;
}
console.log(JSON.stringify(message));
switch (message.method) {
case 'gotoBank':
ui.close();
@ -560,6 +562,18 @@ 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.
ui.open(MARKETPLACES_URL, MARKETPLACES_INJECT_SCRIPT_URL);
break;
case 'checkout_rezClicked':
case 'purchases_rezClicked':
case 'tester_rezClicked':
@ -699,7 +713,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 +727,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
@ -769,14 +785,13 @@ var onTabletScreenChanged = function onTabletScreenChanged(type, url) {
var BUTTON_NAME = "MARKET";
var MARKETPLACE_QML_SOURCE = "hifi/commerce/marketplace/Marketplace.qml";
var ui;
function startup() {
ui = new AppUi({
buttonName: BUTTON_NAME,
sortOrder: 9,
home: MARKETPLACE_QML_SOURCE,
home: MARKETPLACE_QML_PATH,
onScreenChanged: onTabletScreenChanged,
onMessage: onQmlMessageReceived
});