From 39ad36a4d03c2fdaad0216ddaeb2209c66cc3cf0 Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Fri, 1 Feb 2019 15:27:17 -0800 Subject: [PATCH] QmlMarketplace - bugfixes and Markup rendering of descriptions * Render markup in descriptions (bold, italic, quote, etc.) * Back button from marketplaces list now works properly * Layout fixes --- .../hifi/commerce/marketplace/Marketplace.qml | 133 +++++++++++------ .../commerce/marketplace/MarketplaceItem.qml | 136 +++++++++++++----- scripts/system/html/js/marketplacesInject.js | 9 +- scripts/system/marketplaces/marketplaces.js | 13 +- 4 files changed, 210 insertions(+), 81 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml b/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml index d32d298acd..a4cf260173 100644 --- a/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml +++ b/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml @@ -32,7 +32,7 @@ Rectangle { property string activeView: "initialize" property int currentSortIndex: 0 - property string sortString: "" + property string sortString: "recent" property string categoryString: "" property string searchString: "" property bool keyboardEnabled: HMD.active @@ -45,6 +45,7 @@ Rectangle { function getMarketplaceItems() { marketplaceItemView.visible = false; itemsList.visible = true; + licenseInfo.visible = false; marketBrowseModel.getFirstPage(); { if(root.searchString !== undefined && root.searchString !== "") { @@ -69,7 +70,6 @@ Rectangle { target: GlobalServices onMyUsernameChanged: { - console.log("LOGIN STATUS CHANGING"); Commerce.getLoginStatus(); } } @@ -333,7 +333,7 @@ Rectangle { break; } } - onTextChanged: root.searchString = text + onAccepted: { root.searchString = searchField.text; getMarketplaceItems(); @@ -474,11 +474,11 @@ Rectangle { anchors { fill: parent - topMargin: 120 + topMargin: 115 bottomMargin: 50 } - visible: true; + visible: true HifiModels.PSFListModel { id: marketBrowseModel @@ -565,17 +565,22 @@ Rectangle { header: Item { id: itemsHeading - + height: childrenRect.height width: parent.width - + + Rectangle { + id: itemsSpacer; + height: 20 + } + Rectangle { id: itemsLoginStatus; anchors { + top: itemsSpacer.bottom left: parent.left right: parent.right leftMargin: 15 - top: parent.top+15 } height: root.isLoggedIn ? 0 : 80 @@ -598,7 +603,7 @@ Rectangle { } width: 80; - text: root.price ? root.price : "LOG IN" + text: "LOG IN" onClicked: { sendToScript({method: 'needsLogIn_loginClicked'}); @@ -687,6 +692,7 @@ Rectangle { } Item { id: sort + visible: searchString === undefined || searchString === "" anchors { top: searchScope.bottom; @@ -695,7 +701,7 @@ Rectangle { topMargin: 10; leftMargin: 15; } - height: childrenRect.height + height: visible ? childrenRect.height : 0 RalewayRegular { id: sortText @@ -771,6 +777,7 @@ Rectangle { focus: true clip: true highlightFollowsCurrentItem: false + currentIndex: 1; delegate: SortButton { width: 80 @@ -818,25 +825,39 @@ Rectangle { id: marketplaceItemView anchors.fill: parent - anchors.topMargin: 120 + anchors.topMargin: 115 + anchors.bottomMargin: 50 width: parent.width visible: false - + ScrollView { id: marketplaceItemScrollView - anchors.fill: parent; + anchors.fill: parent clip: true ScrollBar.vertical.policy: ScrollBar.AlwaysOn contentWidth: parent.width + contentHeight: childrenRect.height + + function resize() { + contentHeight = (marketplaceItemContent.y - itemSpacer.y + marketplaceItemContent.height); + } + + Item { + id: itemSpacer + anchors.top: parent.top + height: 15 + } Rectangle { id: itemLoginStatus; anchors { left: parent.left right: parent.right + top: itemSpacer.bottom + topMargin: 10 leftMargin: 15 rightMargin: 15 } @@ -861,7 +882,7 @@ Rectangle { } width: 80; - text: root.price ? root.price : "LOG IN" + text: "LOG IN" onClicked: { sendToScript({method: 'needsLogIn_loginClicked'}); @@ -890,9 +911,9 @@ Rectangle { Rectangle { id: marketplaceItemContent - anchors.top: itemLoginStatus.bottom; + anchors.top: itemLoginStatus.bottom width: parent.width - height: childrenRect.height + 100 + height: childrenRect.height; RalewaySemiBold { id: backText @@ -900,6 +921,7 @@ Rectangle { anchors { top: parent.top left: parent.left + topMargin: 10 leftMargin: 15 bottomMargin: 10 } @@ -944,6 +966,10 @@ Rectangle { categoriesText.text = category; getMarketplaceItems(); } + + onResized: { + marketplaceItemScrollView.resize(); + } } } } @@ -975,37 +1001,64 @@ Rectangle { leftMargin: 15 } - HiFiGlyphs { - id: footerGlyph + Item { + id: footerText + anchors.fill: parent + visible: itemsList.visible + + HiFiGlyphs { + id: footerGlyph + + anchors { + left: parent.left + top: parent.top + bottom: parent.bottom + rightMargin: 10 + } + + text: hifi.glyphs.info + size: 34 + color: hifi.colors.white + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + RalewaySemiBold { + id: footerInfo + + anchors { + left: footerGlyph.right + top: parent.top + bottom: parent.bottom + } + + text: "Get items from Clara.io!" + color: hifi.colors.white + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + size: 18 + } + } + + HifiControlsUit.Button { anchors { left: parent.left top: parent.top bottom: parent.bottom + topMargin: 10 + bottomMargin: 10 + leftMargin: 10 rightMargin: 10 } - text: hifi.glyphs.info - size: 34 - color: hifi.colors.white - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - } + visible: marketplaceItemView.visible + text: "< BACK" + width: 100 - RalewaySemiBold { - id: footerInfo - - anchors { - left: footerGlyph.right - top: parent.top - bottom: parent.bottom + onClicked: { + getMarketplaceItems(); } - - text: "Get items from Clara.io!" - color: hifi.colors.white - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - size: 18 } HifiControlsUit.Button { @@ -1023,7 +1076,7 @@ Rectangle { width: 180 onClicked: { - sendToScript({method: 'marketplace_marketplaces'}); + sendToScript({method: 'marketplace_marketplaces', itemId: marketplaceItemView.visible ? marketplaceItem.item_id : undefined}); } } } @@ -1041,7 +1094,7 @@ Rectangle { anchors { fill: root - topMargin: 100 + topMargin: 120 bottomMargin: 0 } @@ -1052,7 +1105,7 @@ Rectangle { anchors { bottomMargin: 1 - topMargin: 50 + topMargin: 60 leftMargin: 1 rightMargin: 1 fill: parent diff --git a/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml b/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml index 0478f38764..b7e9a711d2 100644 --- a/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml +++ b/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml @@ -15,6 +15,7 @@ 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 @@ -49,6 +50,11 @@ Rectangle { categoriesListModel.append({"category":category}); }); } + + onDescriptionChanged: { + descriptionTextModel.clear(); + descriptionTextModel.append({text: description}) + } signal buy() signal categoryClicked(string category) @@ -63,7 +69,7 @@ Rectangle { onMarketplaceItemLikeResult: { if (result.status !== 'success') { - console.log("Failed to get Marketplace Categories", result.data.message); + console.log("Like/Unlike item", result.data.message); } else { root.liked = !root.liked; root.likes = root.liked ? root.likes + 1 : root.likes - 1; @@ -98,24 +104,33 @@ Rectangle { 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; + left: parent.left + right: parent.right + leftMargin: 15 + rightMargin: 15 } - height: childrenRect.height; + height: footer.y - header.y + footer.height Rectangle { id: header anchors { - left: parent.left; - right: parent.right; - top: parent.top; + left: parent.left + right: parent.right + top: parent.top } - height: 50; + height: 50 RalewaySemiBold { id: nameText @@ -137,10 +152,10 @@ Rectangle { id: likes anchors { - top: parent.top; - right: parent.right; - bottom: parent.bottom; - rightMargin: 5; + top: parent.top + right: parent.right + bottom: parent.bottom + rightMargin: 5 } RalewaySemiBold { @@ -216,7 +231,11 @@ Rectangle { right: parent.right; top: itemImage.bottom; } - height: childrenRect.height + height: categoriesList.y - buyButton.y + categoriesList.height + + function evalHeight() { + height = categoriesList.y - buyButton.y + categoriesList.height; + } HifiControlsUit.Button { id: buyButton @@ -309,7 +328,7 @@ Rectangle { top: postedLabel.bottom left: parent.left right: parent.right - topMargin: 10 + topMargin: 5 } text: { getFormattedDate(root.created_at); } @@ -360,6 +379,7 @@ Rectangle { anchors.top: licenseLabel.bottom anchors.left: parent.left + anchors.topMargin: 5 width: paintedWidth text: root.license @@ -371,9 +391,10 @@ Rectangle { RalewaySemiBold { id: licenseHelp - anchors.top: licenseText.bottom; - anchors.left: parent.left; - width: paintedWidth; + anchors.top: licenseText.bottom + anchors.left: parent.left + anchors.topMargin: 5 + width: paintedWidth text: "More about this license" size: 14 @@ -413,6 +434,7 @@ Rectangle { Item { id: descriptionItem + property string text: "" anchors { top: licenseItem.bottom @@ -421,13 +443,16 @@ Rectangle { 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 @@ -435,18 +460,60 @@ Rectangle { verticalAlignment: Text.AlignVCenter } - RalewaySemiBold { - id: descriptionText + //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 + // verticalAlignment: Text.AlignVCenter + // wrapMode: Text.Wrap + //} + + + ListModel { + id: descriptionTextModel + } + + ListView { + id: descriptionTextView; anchors.top: descriptionLabel.bottom anchors.left: parent.left - width: parent.width + anchors.right: parent.right - text: root.description - size: 14 - color: hifi.colors.lightGray - verticalAlignment: Text.AlignVCenter - wrapMode: Text.Wrap + model: descriptionTextModel + interactive: false + + delegate: Component { + Rectangle { + id: descriptionWebRect + width: parent.width + height: 5 + WebEngineView { + id: descriptionWebView + anchors.fill: parent + + Component.onCompleted: { + loadHtml(""+model.text+""); + } + + onContentsSizeChanged: { + descriptionWebRect.height = contentsSize.height; + descriptionTextView.height = contentsSize.height; + } + + onNewViewRequested: function(request) { + sendToScript({method: 'marketplace_open_link', link: request.requestedUrl}); + } + } + } + } } } @@ -460,7 +527,7 @@ Rectangle { right: parent.right } width: parent.width - height: childrenRect.height + height: childrenRect.height + 50 RalewaySemiBold { id: categoryLabel @@ -480,12 +547,13 @@ Rectangle { ListView { anchors { - left: parent.left; - right: parent.right; - top: categoryLabel.bottom; + left: parent.left + right: parent.right + top: categoryLabel.bottom + bottomMargin: 15 } - height: 20*model.count + height: 24*model.count+10 model: categoriesListModel delegate: RalewaySemiBold { @@ -496,7 +564,7 @@ Rectangle { text: model.category size: 14 - height: 20 + height: 24 color: hifi.colors.blueHighlight verticalAlignment: Text.AlignVCenter diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js index 74bf8d3fec..8d408169ba 100644 --- a/scripts/system/html/js/marketplacesInject.js +++ b/scripts/system/html/js/marketplacesInject.js @@ -76,9 +76,12 @@ if (document.referrer !== "") { window.history.back(); } else { - EventBridge.emitWebEvent(JSON.stringify({ - type: GOTO_MARKETPLACE - })); + 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 () { diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index b7a6b951a9..c085763fad 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -41,7 +41,6 @@ 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"; var CLARA_DOWNLOAD_TITLE = "Preparing Download"; var messageBox = null; @@ -437,9 +436,8 @@ function rezEntity(itemHref, itemType, marketplaceItemTesterId) { 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_MARKETPLACE) { - openMarketplace(); + 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. @@ -569,7 +567,14 @@ var onQmlMessageReceived = function onQmlMessageReceived(message) { 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); + 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':