mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge pull request #6687 from jherico/marketplace
Support the marketplace in QML
This commit is contained in:
commit
3dfc48e205
8 changed files with 130 additions and 41 deletions
|
@ -140,9 +140,33 @@ var importingSVOTextOverlay = Overlays.addOverlay("text", {
|
|||
});
|
||||
|
||||
var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace";
|
||||
var marketplaceWindow = new WebWindow('Marketplace', MARKETPLACE_URL, 900, 700, false);
|
||||
var marketplaceWindow = new OverlayWebWindow('Marketplace', "about:blank", 900, 700, false);
|
||||
marketplaceWindow.setVisible(false);
|
||||
|
||||
function showMarketplace(marketplaceID) {
|
||||
var url = MARKETPLACE_URL;
|
||||
if (marketplaceID) {
|
||||
url = url + "/items/" + marketplaceID;
|
||||
}
|
||||
print("setting marketplace URL to " + url);
|
||||
marketplaceWindow.setURL(url);
|
||||
marketplaceWindow.setVisible(true);
|
||||
marketplaceWindow.raise();
|
||||
}
|
||||
|
||||
function hideMarketplace() {
|
||||
marketplaceWindow.setVisible(false);
|
||||
marketplaceWindow.setURL("about:blank");
|
||||
}
|
||||
|
||||
function toggleMarketplace() {
|
||||
if (marketplaceWindow.visible) {
|
||||
hideMarketplace();
|
||||
} else {
|
||||
showMarketplace();
|
||||
}
|
||||
}
|
||||
|
||||
var toolBar = (function() {
|
||||
var that = {},
|
||||
toolBar,
|
||||
|
@ -413,12 +437,9 @@ var toolBar = (function() {
|
|||
newModelButtonDown = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (browseMarketplaceButton === toolBar.clicked(clickedOverlay)) {
|
||||
if (marketplaceWindow.url != MARKETPLACE_URL) {
|
||||
marketplaceWindow.setURL(MARKETPLACE_URL);
|
||||
}
|
||||
marketplaceWindow.setVisible(true);
|
||||
marketplaceWindow.raise();
|
||||
toggleMarketplace();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1336,6 +1357,7 @@ function getPositionToCreateEntity() {
|
|||
}
|
||||
|
||||
function importSVO(importURL) {
|
||||
print("Import URL requested: " + importURL)
|
||||
if (!Entities.canAdjustLocks()) {
|
||||
Window.alert(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG);
|
||||
return;
|
||||
|
@ -1574,11 +1596,7 @@ PropertiesTool = function(opts) {
|
|||
pushCommandForSelections();
|
||||
selectionManager._update();
|
||||
} else if (data.type == "showMarketplace") {
|
||||
if (marketplaceWindow.url != data.url) {
|
||||
marketplaceWindow.setURL(data.url);
|
||||
}
|
||||
marketplaceWindow.setVisible(true);
|
||||
marketplaceWindow.raise();
|
||||
showMarketplace();
|
||||
} else if (data.type == "action") {
|
||||
if (data.action == "moveSelectionToGrid") {
|
||||
if (selectionManager.hasSelection()) {
|
||||
|
@ -1859,12 +1877,7 @@ var propertyMenu = PopupMenu();
|
|||
|
||||
propertyMenu.onSelectMenuItem = function(name) {
|
||||
if (propertyMenu.marketplaceID) {
|
||||
var url = MARKETPLACE_URL + "/items/" + propertyMenu.marketplaceID;
|
||||
if (marketplaceWindow.url != url) {
|
||||
marketplaceWindow.setURL(url);
|
||||
}
|
||||
marketplaceWindow.setVisible(true);
|
||||
marketplaceWindow.raise();
|
||||
showMarketplace(propertyMenu.marketplaceID);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -13,12 +13,18 @@ VrDialog {
|
|||
HifiConstants { id: hifi }
|
||||
title: "WebWindow"
|
||||
resizable: true
|
||||
// Don't destroy on close... otherwise the JS/C++ will have a dangling pointer
|
||||
destroyOnCloseButton: false
|
||||
contentImplicitWidth: clientArea.implicitWidth
|
||||
contentImplicitHeight: clientArea.implicitHeight
|
||||
backgroundColor: "#7f000000"
|
||||
property url source: "about:blank"
|
||||
|
||||
signal navigating(string url)
|
||||
function stop() {
|
||||
webview.stop();
|
||||
}
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
enabled = true
|
||||
|
@ -26,18 +32,14 @@ VrDialog {
|
|||
webview.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
|
||||
console.log("Web Window JS message: " + sourceID + " " + lineNumber + " " + message);
|
||||
});
|
||||
|
||||
webview.loadingChanged.connect(handleWebviewLoading)
|
||||
}
|
||||
|
||||
|
||||
function handleWebviewLoading(loadRequest) {
|
||||
var HIFI_URL_PATTERN = /^hifi:\/\//;
|
||||
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
|
||||
var newUrl = loadRequest.url.toString();
|
||||
if (newUrl.match(HIFI_URL_PATTERN)) {
|
||||
root.navigating(newUrl);
|
||||
}
|
||||
root.navigating(newUrl)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,9 +56,18 @@ VrDialog {
|
|||
id: webview
|
||||
url: root.source
|
||||
anchors.fill: parent
|
||||
profile: WebEngineProfile {
|
||||
httpUserAgent: "Mozilla/5.0 (HighFidelityInterface)"
|
||||
onUrlChanged: {
|
||||
var currentUrl = url.toString();
|
||||
var newUrl = urlFixer.fixupUrl(currentUrl);
|
||||
if (newUrl != currentUrl) {
|
||||
url = newUrl;
|
||||
}
|
||||
}
|
||||
profile: WebEngineProfile {
|
||||
id: webviewProfile
|
||||
httpUserAgent: "Mozilla/5.0 (HighFidelityInterface)"
|
||||
storageName: "qmlWebEngine"
|
||||
}
|
||||
}
|
||||
} // item
|
||||
} // dialog
|
||||
|
|
|
@ -4201,7 +4201,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
scriptEngine->registerGlobalObject("ScriptDiscoveryService", this->getRunningScriptsWidget());
|
||||
}
|
||||
|
||||
bool Application::canAcceptURL(const QString& urlString) {
|
||||
bool Application::canAcceptURL(const QString& urlString) const {
|
||||
QUrl url(urlString);
|
||||
if (urlString.startsWith(HIFI_URL_SCHEME)) {
|
||||
return true;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <SimpleMovingAverage.h>
|
||||
#include <StDev.h>
|
||||
#include <ViewFrustum.h>
|
||||
#include <AbstractUriHandler.h>
|
||||
|
||||
#include "avatar/AvatarUpdate.h"
|
||||
#include "avatar/MyAvatar.h"
|
||||
|
@ -88,7 +89,7 @@ class Application;
|
|||
#endif
|
||||
#define qApp (static_cast<Application*>(QCoreApplication::instance()))
|
||||
|
||||
class Application : public QApplication, public AbstractViewStateInterface, public AbstractScriptingServicesInterface {
|
||||
class Application : public QApplication, public AbstractViewStateInterface, public AbstractScriptingServicesInterface, public AbstractUriHandler {
|
||||
Q_OBJECT
|
||||
|
||||
// TODO? Get rid of those
|
||||
|
@ -219,8 +220,8 @@ public:
|
|||
QString getScriptsLocation();
|
||||
void setScriptsLocation(const QString& scriptsLocation);
|
||||
|
||||
bool canAcceptURL(const QString& url);
|
||||
bool acceptURL(const QString& url, bool defaultUpload = false);
|
||||
virtual bool canAcceptURL(const QString& url) const override;
|
||||
virtual bool acceptURL(const QString& url, bool defaultUpload = false) override;
|
||||
|
||||
void setMaxOctreePacketsPerSecond(int maxOctreePPS);
|
||||
int getMaxOctreePacketsPerSecond();
|
||||
|
|
19
libraries/networking/src/AbstractUriHandler.h
Normal file
19
libraries/networking/src/AbstractUriHandler.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2015/12/17
|
||||
// Copyright 2013-2015 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_network_AbstractUriHandler_h
|
||||
#define hifi_network_AbstractUriHandler_h
|
||||
|
||||
class AbstractUriHandler {
|
||||
public:
|
||||
virtual bool canAcceptURL(const QString& url) const = 0;
|
||||
virtual bool acceptURL(const QString& url, bool defaultUpload = false) = 0;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1867,7 +1867,7 @@ bool Octree::readJSONFromStream(unsigned long streamLength, QDataStream& inputSt
|
|||
|
||||
QByteArray jsonBuffer;
|
||||
char* rawData = new char[READ_JSON_BUFFER_SIZE];
|
||||
while (true) {
|
||||
while (!inputStream.atEnd()) {
|
||||
int got = inputStream.readRawData(rawData, READ_JSON_BUFFER_SIZE - 1);
|
||||
if (got < 0) {
|
||||
qCritical() << "error while reading from json stream";
|
||||
|
|
|
@ -10,18 +10,20 @@
|
|||
|
||||
#include <mutex>
|
||||
|
||||
#include <QtCore/QThread>
|
||||
#include <QtScript/QScriptContext>
|
||||
#include <QtScript/QScriptEngine>
|
||||
|
||||
#include <QtQuick/QQuickItem>
|
||||
|
||||
#include <QtWebSockets/QWebSocketServer>
|
||||
#include <QtWebSockets/QWebSocket>
|
||||
#include <QtWebChannel/QWebChannel>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtCore/QUrlQuery>
|
||||
#include <QtCore/QThread>
|
||||
#include <QtQml/QQmlContext>
|
||||
#include <QtScript/QScriptContext>
|
||||
#include <QtScript/QScriptEngine>
|
||||
#include <QtWebChannel/QWebChannel>
|
||||
#include <QtWebSockets/QWebSocketServer>
|
||||
#include <QtWebSockets/QWebSocket>
|
||||
|
||||
#include <AbstractUriHandler.h>
|
||||
#include <AddressManager.h>
|
||||
#include <DependencyManager.h>
|
||||
|
||||
|
@ -83,17 +85,41 @@ void QmlWebWindowClass::setupServer() {
|
|||
}
|
||||
}
|
||||
|
||||
class UrlFixer : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_INVOKABLE QString fixupUrl(const QString& originalUrl) {
|
||||
static const QString ACCESS_TOKEN_PARAMETER = "access_token";
|
||||
static const QString ALLOWED_HOST = "metaverse.highfidelity.com";
|
||||
QString result = originalUrl;
|
||||
QUrl url(originalUrl);
|
||||
QUrlQuery query(url);
|
||||
if (url.host() == ALLOWED_HOST && query.allQueryItemValues(ACCESS_TOKEN_PARAMETER).empty()) {
|
||||
qDebug() << "Updating URL with auth token";
|
||||
AccountManager& accountManager = AccountManager::getInstance();
|
||||
query.addQueryItem(ACCESS_TOKEN_PARAMETER, accountManager.getAccountInfo().getAccessToken().token);
|
||||
url.setQuery(query.query());
|
||||
result = url.toString();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
static UrlFixer URL_FIXER;
|
||||
|
||||
// Method called by Qt scripts to create a new web window in the overlay
|
||||
QScriptValue QmlWebWindowClass::constructor(QScriptContext* context, QScriptEngine* engine) {
|
||||
QmlWebWindowClass* retVal { nullptr };
|
||||
const QString title = context->argument(0).toString();
|
||||
QString url = context->argument(1).toString();
|
||||
if (!url.startsWith("http") && !url.startsWith("file://")) {
|
||||
if (!url.startsWith("http") && !url.startsWith("file://") && !url.startsWith("about:")) {
|
||||
url = QUrl::fromLocalFile(url).toString();
|
||||
}
|
||||
const int width = std::max(100, std::min(1280, context->argument(2).toInt32()));;
|
||||
const int height = std::max(100, std::min(720, context->argument(3).toInt32()));;
|
||||
|
||||
|
||||
// Build the event bridge and wrapper on the main thread
|
||||
QMetaObject::invokeMethod(DependencyManager::get<OffscreenUi>().data(), "load", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(const QString&, "QmlWebWindow.qml"),
|
||||
|
@ -101,6 +127,7 @@ QScriptValue QmlWebWindowClass::constructor(QScriptContext* context, QScriptEngi
|
|||
setupServer();
|
||||
retVal = new QmlWebWindowClass(object);
|
||||
webChannel.registerObject(url.toLower(), retVal);
|
||||
context->setContextProperty("urlFixer", &URL_FIXER);
|
||||
retVal->setTitle(title);
|
||||
retVal->setURL(url);
|
||||
retVal->setSize(width, height);
|
||||
|
@ -119,7 +146,23 @@ QmlWebWindowClass::QmlWebWindowClass(QObject* qmlWindow)
|
|||
}
|
||||
|
||||
void QmlWebWindowClass::handleNavigation(const QString& url) {
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(url);
|
||||
bool handled = false;
|
||||
|
||||
if (url.contains(HIFI_URL_PATTERN)) {
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(url);
|
||||
handled = true;
|
||||
} else {
|
||||
static auto handler = dynamic_cast<AbstractUriHandler*>(qApp);
|
||||
if (handler) {
|
||||
if (handler->canAcceptURL(url)) {
|
||||
handled = handler->acceptURL(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
QMetaObject::invokeMethod(_qmlWindow, "stop", Qt::AutoConnection);
|
||||
}
|
||||
}
|
||||
|
||||
void QmlWebWindowClass::setVisible(bool visible) {
|
||||
|
@ -202,6 +245,7 @@ QString QmlWebWindowClass::getURL() const {
|
|||
QMetaObject::invokeMethod(const_cast<QmlWebWindowClass*>(this), "getURL", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
return _qmlWindow->property(URL_PROPERTY).toString();
|
||||
}
|
||||
|
||||
|
|
|
@ -10,11 +10,12 @@
|
|||
#define hifi_ui_QmlWebWindowClass_h
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <GLMHelpers.h>
|
||||
#include <QtScript/QScriptValue>
|
||||
#include <QtQuick/QQuickItem>
|
||||
#include <QtWebChannel/QWebChannelAbstractTransport>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
class QScriptEngine;
|
||||
class QScriptContext;
|
||||
class QmlWebWindowClass;
|
||||
|
|
Loading…
Reference in a new issue