overte-lubosz/scripts/system/marketplaces/marketplaces.js

830 lines
33 KiB
JavaScript

//
// marketplaces.js
//
// Created by Eric Levin on 8 Jan 2016
// Copyright 2016 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
//
/* global Tablet, Script, HMD, UserActivityLogger, Entities, Account, Wallet, ContextOverlay, Settings, Camera, Vec3,
Quat, MyAvatar, Clipboard, Menu, Grid, Uuid, GlobalServices, openLoginWindow, getConnectionData, Overlays, SoundCache,
DesktopPreviewProvider, ResourceRequestObserver */
/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */
var selectionDisplay = null; // for gridTool.js to ignore
(function () { // BEGIN LOCAL_SCOPE
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;
var REZZING_SOUND = SoundCache.getSound(Script.resolvePath("../assets/sounds/rezzing.wav"));
// Event bridge messages.
var CLARA_IO_DOWNLOAD = "CLARA.IO DOWNLOAD";
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";
var CLARA_DOWNLOAD_TITLE = "Preparing Download";
var messageBox = null;
var isDownloadBeingCancelled = false;
var CANCEL_BUTTON = 4194304; // QMessageBox::Cancel
var NO_BUTTON = 0; // QMessageBox::NoButton
var NO_PERMISSIONS_ERROR_MESSAGE = "Cannot download model because you can't write to \nthe domain's Asset Server.";
var resourceRequestEvents = [];
function signalResourceRequestEvent(data) {
// Once we can tie resource request events to specific resources,
// we will have to update the "0" in here.
var resourceData = "from: " + data.extra + ": " + data.url.toString().replace("__NONE__,", "");
if (resourceObjectsInTest[0].resourceDataArray.indexOf(resourceData) === -1) {
resourceObjectsInTest[0].resourceDataArray.push(resourceData);
resourceObjectsInTest[0].resourceAccessEventText += "[" + data.date.toISOString() + "] " +
resourceData + "\n";
ui.tablet.sendToQml({
method: "resourceRequestEvent",
data: data,
resourceAccessEventText: resourceObjectsInTest[0].resourceAccessEventText
});
}
}
function onResourceRequestEvent(data) {
// Once we can tie resource request events to specific resources,
// we will have to update the "0" in here.
if (resourceObjectsInTest[0] && resourceObjectsInTest[0].currentlyRecordingResources) {
var resourceRequestEvent = {
"date": new Date(),
"url": data.url,
"callerId": data.callerId,
"extra": data.extra
};
resourceRequestEvents.push(resourceRequestEvent);
signalResourceRequestEvent(resourceRequestEvent);
}
}
function onMessageBoxClosed(id, button) {
if (id === messageBox && button === CANCEL_BUTTON) {
isDownloadBeingCancelled = true;
messageBox = null;
ui.sendToHtml({
type: CLARA_IO_CANCEL_DOWNLOAD
});
}
}
function onCanWriteAssetsChanged() {
ui.sendToHtml({
type: CAN_WRITE_ASSETS,
canWriteAssets: Entities.canWriteAssets()
});
}
var tabletShouldBeVisibleInSecondaryCamera = false;
function setTabletVisibleInSecondaryCamera(visibleInSecondaryCam) {
if (visibleInSecondaryCam) {
// if we're potentially showing the tablet, only do so if it was visible before
if (!tabletShouldBeVisibleInSecondaryCamera) {
return;
}
} else {
// if we're hiding the tablet, check to see if it was visible in the first place
tabletShouldBeVisibleInSecondaryCamera = Entities.getEntityProperties(HMD.tabletID, ["isVisibleInSecondaryCamera"]).isVisibleInSecondaryCamera;
}
Overlays.editOverlay(HMD.tabletID, { isVisibleInSecondaryCamera: visibleInSecondaryCam });
Overlays.editOverlay(HMD.homeButtonID, { isVisibleInSecondaryCamera: visibleInSecondaryCam });
Overlays.editOverlay(HMD.homeButtonHighlightID, { isVisibleInSecondaryCamera: visibleInSecondaryCam });
Overlays.editOverlay(HMD.tabletScreenID, { isVisibleInSecondaryCamera: visibleInSecondaryCam });
}
function openWallet() {
ui.open(MARKETPLACE_WALLET_QML_PATH);
}
function setupWallet(referrer) {
// Needs to be done within the QML page in order to get access to QmlCommerce
openWallet();
var ALLOWANCE_FOR_EVENT_BRIDGE_SETUP = 0;
Script.setTimeout(function () {
ui.tablet.sendToQml({
method: 'updateWalletReferrer',
referrer: referrer
});
}, ALLOWANCE_FOR_EVENT_BRIDGE_SETUP);
}
function onMarketplaceOpen(referrer) {
var match;
if (Account.loggedIn && walletNeedsSetup()) {
if (referrer === MARKETPLACE_URL_INITIAL) {
setupWallet('marketplace cta');
} else {
match = referrer.match(/\/item\/(\w+)$/);
if (match && match[1]) {
setupWallet(match[1]);
} else if (referrer.indexOf(METAVERSE_SERVER_URL) === -1) { // not a url
setupWallet(referrer);
} else {
print("WARNING: opening marketplace to", referrer, "without wallet setup.");
}
}
}
}
function openMarketplace(optionalItem, edition) {
ui.open(MARKETPLACE_QML_PATH);
if (optionalItem) {
ui.tablet.sendToQml({
method: 'updateMarketplaceQMLItem',
params: { itemId: optionalItem, edition: edition }
});
}
}
// Function Name: wireQmlEventBridge()
//
// Description:
// -Used to connect/disconnect the script's response to the tablet's "fromQml" signal. Set the "on" argument to enable or
// disable to event bridge.
//
// Relevant Variables:
// -hasEventBridge: true/false depending on whether we've already connected the event bridge.
var hasEventBridge = false;
function wireQmlEventBridge(on) {
if (!ui.tablet) {
print("Warning in wireQmlEventBridge(): 'tablet' undefined!");
return;
}
if (on) {
if (!hasEventBridge) {
ui.tablet.fromQml.connect(onQmlMessageReceived);
hasEventBridge = true;
}
} else {
if (hasEventBridge) {
ui.tablet.fromQml.disconnect(onQmlMessageReceived);
hasEventBridge = false;
}
}
}
var contextOverlayEntity = "";
function openInspectionCertificateQML(currentEntityWithContextOverlay) {
ui.open(MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH);
contextOverlayEntity = currentEntityWithContextOverlay;
}
function setCertificateInfo(currentEntityWithContextOverlay, itemCertificateId) {
var certificateId = itemCertificateId ||
(Entities.getEntityProperties(currentEntityWithContextOverlay, ['certificateID']).certificateID);
ui.tablet.sendToQml({
method: 'inspectionCertificate_setCertificateId',
entityId: currentEntityWithContextOverlay,
certificateId: certificateId
});
}
function onUsernameChanged() {
if (onMarketplaceScreen) {
openMarketplace();
}
}
function walletNeedsSetup() {
return WalletScriptingInterface.walletStatus === 1;
}
function sendCommerceSettings() {
ui.sendToHtml({
type: "marketplaces",
action: "commerceSetting",
data: {
commerceMode: Settings.getValue("commerce", true),
userIsLoggedIn: Account.loggedIn,
walletNeedsSetup: walletNeedsSetup(),
metaverseServerURL: Account.metaverseServerURL,
limitedCommerce: WalletScriptingInterface.limitedCommerce
}
});
}
var grid = new Grid();
function adjustPositionPerBoundingBox(position, direction, registration, dimensions, orientation) {
// Adjust the position such that the bounding box (registration, dimenions, and orientation) lies behind the original
// position in the given direction.
var CORNERS = [
{ x: 0, y: 0, z: 0 },
{ x: 0, y: 0, z: 1 },
{ x: 0, y: 1, z: 0 },
{ x: 0, y: 1, z: 1 },
{ x: 1, y: 0, z: 0 },
{ x: 1, y: 0, z: 1 },
{ x: 1, y: 1, z: 0 },
{ x: 1, y: 1, z: 1 }
];
// Go through all corners and find least (most negative) distance in front of position.
var distance = 0;
for (var i = 0, length = CORNERS.length; i < length; i++) {
var cornerVector =
Vec3.multiplyQbyV(orientation, Vec3.multiplyVbyV(Vec3.subtract(CORNERS[i], registration), dimensions));
var cornerDistance = Vec3.dot(cornerVector, direction);
distance = Math.min(cornerDistance, distance);
}
position = Vec3.sum(Vec3.multiply(distance, direction), position);
return position;
}
var HALF_TREE_SCALE = 16384;
function getPositionToCreateEntity(extra) {
var CREATE_DISTANCE = 2;
var position;
var delta = extra !== undefined ? extra : 0;
if (Camera.mode === "entity" || Camera.mode === "independent") {
position = Vec3.sum(Camera.position, Vec3.multiply(Quat.getForward(Camera.orientation), CREATE_DISTANCE + delta));
} else {
position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getForward(MyAvatar.orientation), CREATE_DISTANCE + delta));
position.y += 0.5;
}
if (position.x > HALF_TREE_SCALE || position.y > HALF_TREE_SCALE || position.z > HALF_TREE_SCALE) {
return null;
}
return position;
}
function defaultFor(arg, val) {
return typeof arg !== 'undefined' ? arg : val;
}
var CERT_ID_URLPARAM_LENGTH = 15; // length of "certificate_id="
function rezEntity(itemHref, itemType, marketplaceItemTesterId) {
var isWearable = itemType === "wearable";
var success = Clipboard.importEntities(itemHref, true, marketplaceItemTesterId);
var wearableLocalPosition = null;
var wearableLocalRotation = null;
var wearableLocalDimensions = null;
var wearableDimensions = null;
marketplaceItemTesterId = defaultFor(marketplaceItemTesterId, -1);
if (itemType === "contentSet") {
console.log("Item is a content set; codepath shouldn't go here.");
return;
}
if (isWearable) {
var wearableTransforms = Settings.getValue("io.highfidelity.avatarStore.checkOut.transforms");
if (!wearableTransforms) {
// TODO delete this clause
wearableTransforms = Settings.getValue("io.highfidelity.avatarStore.checkOut.tranforms");
}
var certPos = itemHref.search("certificate_id="); // TODO how do I parse a URL from here?
if (certPos >= 0) {
certPos += CERT_ID_URLPARAM_LENGTH;
var certURLEncoded = itemHref.substring(certPos);
var certB64Encoded = decodeURIComponent(certURLEncoded);
for (var key in wearableTransforms) {
if (wearableTransforms.hasOwnProperty(key)) {
var certificateTransforms = wearableTransforms[key].certificateTransforms;
if (certificateTransforms) {
for (var certID in certificateTransforms) {
if (certificateTransforms.hasOwnProperty(certID) &&
certID === certB64Encoded) {
var certificateTransform = certificateTransforms[certID];
wearableLocalPosition = certificateTransform.localPosition;
wearableLocalRotation = certificateTransform.localRotation;
wearableLocalDimensions = certificateTransform.localDimensions;
wearableDimensions = certificateTransform.dimensions;
}
}
}
}
}
}
}
if (success) {
var VERY_LARGE = 10000;
var isLargeImport = Clipboard.getClipboardContentsLargestDimension() >= VERY_LARGE;
var position = Vec3.ZERO;
if (!isLargeImport) {
position = getPositionToCreateEntity(Clipboard.getClipboardContentsLargestDimension() / 2);
}
if (position !== null && position !== undefined) {
var pastedEntityIDs = Clipboard.pasteEntities(position);
if (!isLargeImport) {
// The first entity in Clipboard gets the specified position with the rest being relative to it. Therefore, move
// entities after they're imported so that they're all the correct distance in front of and with geometric mean
// centered on the avatar/camera direction.
var deltaPosition = Vec3.ZERO;
var entityPositions = [];
var entityParentIDs = [];
var propType = Entities.getEntityProperties(pastedEntityIDs[0], ["type"]).type;
var NO_ADJUST_ENTITY_TYPES = ["Zone", "Light", "ParticleEffect"];
if (NO_ADJUST_ENTITY_TYPES.indexOf(propType) === -1) {
var targetDirection;
if (Camera.mode === "entity" || Camera.mode === "independent") {
targetDirection = Camera.orientation;
} else {
targetDirection = MyAvatar.orientation;
}
targetDirection = Vec3.multiplyQbyV(targetDirection, Vec3.UNIT_Z);
var targetPosition = getPositionToCreateEntity();
// Distance to move entities parallel to targetDirection.
var deltaParallel = HALF_TREE_SCALE;
// Distance to move entities perpendicular to targetDirection.
var deltaPerpendicular = Vec3.ZERO;
for (var i = 0, length = pastedEntityIDs.length; i < length; i++) {
var curLoopEntityProps = Entities.getEntityProperties(pastedEntityIDs[i], ["position", "dimensions",
"registrationPoint", "rotation", "parentID"]);
var adjustedPosition = adjustPositionPerBoundingBox(targetPosition, targetDirection,
curLoopEntityProps.registrationPoint, curLoopEntityProps.dimensions, curLoopEntityProps.rotation);
var delta = Vec3.subtract(adjustedPosition, curLoopEntityProps.position);
var distance = Vec3.dot(delta, targetDirection);
deltaParallel = Math.min(distance, deltaParallel);
deltaPerpendicular = Vec3.sum(Vec3.subtract(delta, Vec3.multiply(distance, targetDirection)),
deltaPerpendicular);
entityPositions[i] = curLoopEntityProps.position;
entityParentIDs[i] = curLoopEntityProps.parentID;
}
deltaPerpendicular = Vec3.multiply(1 / pastedEntityIDs.length, deltaPerpendicular);
deltaPosition = Vec3.sum(Vec3.multiply(deltaParallel, targetDirection), deltaPerpendicular);
}
if (grid.getSnapToGrid()) {
var firstEntityProps = Entities.getEntityProperties(pastedEntityIDs[0], ["position", "dimensions",
"registrationPoint"]);
var positionPreSnap = Vec3.sum(deltaPosition, firstEntityProps.position);
position = grid.snapToSurface(grid.snapToGrid(positionPreSnap, false, firstEntityProps.dimensions,
firstEntityProps.registrationPoint), firstEntityProps.dimensions, firstEntityProps.registrationPoint);
deltaPosition = Vec3.subtract(position, firstEntityProps.position);
}
if (!Vec3.equal(deltaPosition, Vec3.ZERO)) {
for (var editEntityIndex = 0,
numEntities = pastedEntityIDs.length; editEntityIndex < numEntities; editEntityIndex++) {
if (Uuid.isNull(entityParentIDs[editEntityIndex])) {
Entities.editEntity(pastedEntityIDs[editEntityIndex], {
position: Vec3.sum(deltaPosition, entityPositions[editEntityIndex])
});
}
}
}
}
if (isWearable) {
// apply the relative offsets saved during checkout
var offsets = {};
if (wearableLocalPosition) {
offsets.localPosition = wearableLocalPosition;
}
if (wearableLocalRotation) {
offsets.localRotation = wearableLocalRotation;
}
if (wearableLocalDimensions) {
offsets.localDimensions = wearableLocalDimensions;
} else if (wearableDimensions) {
offsets.dimensions = wearableDimensions;
}
// we currently assume a wearable is a single entity
Entities.editEntity(pastedEntityIDs[0], offsets);
}
var rezPosition = Entities.getEntityProperties(pastedEntityIDs[0], "position").position;
Audio.playSound(REZZING_SOUND, {
volume: 1.0,
position: rezPosition,
localOnly: true
});
} else {
Window.notifyEditError("Can't import entities: entities would be out of bounds.");
}
} else {
Window.notifyEditError("There was an error importing the entity file.");
}
}
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(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);
} else if (message.type === QUERY_CAN_WRITE_ASSETS) {
ui.sendToHtml(CAN_WRITE_ASSETS + " " + Entities.canWriteAssets());
} else if (message.type === WARN_USER_NO_PERMISSIONS) {
Window.alert(NO_PERMISSIONS_ERROR_MESSAGE);
} else if (message.type === CLARA_IO_STATUS) {
if (isDownloadBeingCancelled) {
return;
}
var text = message.status;
if (messageBox === null) {
messageBox = Window.openMessageBox(CLARA_DOWNLOAD_TITLE, text, CANCEL_BUTTON, NO_BUTTON);
} else {
Window.updateMessageBox(messageBox, CLARA_DOWNLOAD_TITLE, text, CANCEL_BUTTON, NO_BUTTON);
}
return;
} else if (message.type === CLARA_IO_DOWNLOAD) {
if (messageBox !== null) {
Window.closeMessageBox(messageBox);
messageBox = null;
}
return;
} else if (message.type === CLARA_IO_CANCELLED_DOWNLOAD) {
isDownloadBeingCancelled = false;
} else if (message.type === "CHECKOUT") {
wireQmlEventBridge(true);
ui.open(MARKETPLACE_CHECKOUT_QML_PATH);
ui.tablet.sendToQml({
method: 'updateCheckoutQMLItemID',
params: message
});
} else if (message.type === "REQUEST_SETTING") {
sendCommerceSettings();
} else if (message.type === "PURCHASES") {
referrerURL = message.referrerURL;
filterText = "";
ui.open(MARKETPLACE_PURCHASES_QML_PATH);
} else if (message.type === "LOGIN") {
openLoginWindow();
} else if (message.type === "WALLET_SETUP") {
setupWallet('marketplace cta');
} else if (message.type === "MY_ITEMS") {
filterText = "";
ui.open(MARKETPLACE_PURCHASES_QML_PATH);
wireQmlEventBridge(true);
ui.tablet.sendToQml({
method: 'purchases_showMyItems'
});
}
}
var savedDisablePreviewOption = Menu.isOptionChecked("Disable Preview");
var UI_FADE_TIMEOUT_MS = 150;
function maybeEnableHMDPreview() {
// Set a small timeout to prevent sensitive data from being shown during UI fade
Script.setTimeout(function () {
setTabletVisibleInSecondaryCamera(true);
DesktopPreviewProvider.setPreviewDisabledReason("USER");
Menu.setIsOptionChecked("Disable Preview", savedDisablePreviewOption);
}, UI_FADE_TIMEOUT_MS);
}
var resourceObjectsInTest = [];
function signalNewResourceObjectInTest(resourceObject) {
ui.tablet.sendToQml({
method: "newResourceObjectInTest",
resourceObject: resourceObject
});
}
var onQmlMessageReceived = function onQmlMessageReceived(message) {
if (message.messageSrc === "HTML") {
return;
}
switch (message.method) {
case 'gotoBank':
ui.close();
if (Account.metaverseServerURL.indexOf("staging") >= 0) {
Window.location = "hifi://hifiqa-master-metaverse-staging"; // So that we can test in staging.
} else {
Window.location = "hifi://BankOfHighFidelity";
}
break;
case 'checkout_openRecentActivity':
ui.open(MARKETPLACE_WALLET_QML_PATH);
wireQmlEventBridge(true);
ui.tablet.sendToQml({
method: 'checkout_openRecentActivity'
});
break;
case 'checkout_setUpClicked':
openWallet();
break;
case 'checkout_walletNotSetUp':
wireQmlEventBridge(true);
ui.tablet.sendToQml({
method: 'updateWalletReferrer',
referrer: message.referrer === "itemPage" ? message.itemId : message.referrer
});
openWallet();
break;
case 'checkout_cancelClicked':
openMarketplace(message.itemId);
break;
case 'header_goToPurchases':
case 'checkout_goToPurchases':
filterText = message.filterText;
ui.open(MARKETPLACE_PURCHASES_QML_PATH);
break;
case 'checkout_itemLinkClicked':
openMarketplace(message.itemId);
break;
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':
rezEntity(message.itemHref, message.itemType, message.itemId);
break;
case 'tester_newResourceObject':
var resourceObject = message.resourceObject;
resourceObjectsInTest = []; // REMOVE THIS once we support specific referrers
resourceObject.currentlyRecordingResources = false;
resourceObject.resourceAccessEventText = "";
resourceObjectsInTest[resourceObject.resourceObjectId] = resourceObject;
resourceObjectsInTest[resourceObject.resourceObjectId].resourceDataArray = [];
signalNewResourceObjectInTest(resourceObject);
break;
case 'tester_updateResourceObjectAssetType':
resourceObjectsInTest[message.objectId].assetType = message.assetType;
break;
case 'tester_deleteResourceObject':
delete resourceObjectsInTest[message.objectId];
break;
case 'tester_updateResourceRecordingStatus':
resourceObjectsInTest[message.objectId].currentlyRecordingResources = message.status;
if (message.status) {
resourceObjectsInTest[message.objectId].resourceDataArray = [];
resourceObjectsInTest[message.objectId].resourceAccessEventText = "";
}
break;
case 'header_marketplaceImageClicked':
openMarketplace();
break;
case 'purchases_goToMarketplaceClicked':
openMarketplace();
break;
case 'updateItemClicked':
openMarketplace(message.itemId, message.itemEdition);
break;
case 'passphrasePopup_cancelClicked':
// Should/must NOT check for wallet setup.
openMarketplace();
break;
case 'marketplace_loginClicked':
openLoginWindow();
break;
case 'disableHmdPreview':
if (!savedDisablePreviewOption) {
DesktopPreviewProvider.setPreviewDisabledReason("SECURE_SCREEN");
Menu.setIsOptionChecked("Disable Preview", true);
setTabletVisibleInSecondaryCamera(false);
}
break;
case 'maybeEnableHmdPreview':
maybeEnableHMDPreview();
break;
case 'checkout_openGoTo':
ui.open("hifi/tablet/TabletAddressDialog.qml");
break;
case 'inspectionCertificate_closeClicked':
ui.close();
break;
case 'inspectionCertificate_requestOwnershipVerification':
ContextOverlay.requestOwnershipVerification(message.entity);
break;
case 'inspectionCertificate_showInMarketplaceClicked':
console.log("INSPECTION CERTIFICATE SHOW IN MARKETPLACE CLICKED: " + message.itemId);
openMarketplace(message.itemId);
break;
case 'header_myItemsClicked':
filterText = "";
ui.open(MARKETPLACE_PURCHASES_QML_PATH);
wireQmlEventBridge(true);
ui.tablet.sendToQml({
method: 'purchases_showMyItems'
});
break;
case 'http.request':
// Handled elsewhere, don't log.
break;
// All of these are handled by wallet.js
case 'purchases_updateWearables':
case 'enable_ChooseRecipientNearbyMode':
case 'disable_ChooseRecipientNearbyMode':
case 'sendAsset_sendPublicly':
case 'refreshConnections':
case 'transactionHistory_goToBank':
case 'purchases_walletNotSetUp':
case 'purchases_openGoTo':
case 'purchases_itemInfoClicked':
case 'purchases_itemCertificateClicked':
case 'clearShouldShowDotHistory':
case 'giftAsset':
break;
default:
print('marketplaces.js: Unrecognized message from Checkout.qml');
}
};
function pushResourceObjectsInTest() {
var maxResourceObjectId = -1;
var length = resourceObjectsInTest.length;
for (var i = 0; i < length; i++) {
if (i in resourceObjectsInTest) {
signalNewResourceObjectInTest(resourceObjectsInTest[i]);
var resourceObjectId = resourceObjectsInTest[i].resourceObjectId;
maxResourceObjectId = (maxResourceObjectId < resourceObjectId) ? parseInt(resourceObjectId) : maxResourceObjectId;
}
}
// N.B. Thinking about removing the following sendToQml? Be sure
// that the marketplace item tester QML has heard from us, at least
// so that it can indicate to the user that all of the resoruce
// objects in test have been transmitted to it.
//ui.tablet.sendToQml({ method: "nextObjectIdInTest", id: maxResourceObjectId + 1 });
// Since, for now, we only support 1 object in test, always send id: 0
ui.tablet.sendToQml({ method: "nextObjectIdInTest", id: 0 });
}
// Function Name: onTabletScreenChanged()
//
// Description:
// -Called when the TabletScriptingInterface::screenChanged() signal is emitted. The "type" argument can be either the string
// value of "Home", "Web", "Menu", "QML", or "Closed". The "url" argument is only valid for Web and QML.
var onCommerceScreen = false;
var onInspectionCertificateScreen = false;
var onMarketplaceItemTesterScreen = false;
var onMarketplaceScreen = false;
var onWalletScreen = false;
var onTabletScreenChanged = function onTabletScreenChanged(type, url) {
ui.setCurrentVisibleScreenMetadata(type, url);
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" && (
url.indexOf(MARKETPLACE_CHECKOUT_QML_PATH) !== -1 ||
url === MARKETPLACE_PURCHASES_QML_PATH ||
url.indexOf(MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH) !== -1);
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)
) {
// exiting wallet, commerce, or marketplace item tester screen
maybeEnableHMDPreview();
}
onCommerceScreen = onCommerceScreenNow;
onWalletScreen = onWalletScreenNow;
onMarketplaceItemTesterScreen = onMarketplaceItemTesterScreenNow;
wireQmlEventBridge(onCommerceScreen || onWalletScreen || onMarketplaceItemTesterScreen || onMarketplaceScreenNow);
if (url === MARKETPLACE_PURCHASES_QML_PATH) {
// FIXME? Is there a race condition here in which the event
// bridge may not be up yet? If so, Script.setTimeout(..., 750)
// may help avoid the condition.
ui.tablet.sendToQml({
method: 'updatePurchases',
referrerURL: referrerURL,
filterText: filterText
});
referrerURL = "";
filterText = "";
}
var wasIsOpen = ui.isOpen;
ui.isOpen = (onMarketplaceScreen || onCommerceScreen) && !onWalletScreen;
ui.buttonActive(ui.isOpen);
if (wasIsOpen !== ui.isOpen && Keyboard.raised) {
Keyboard.raised = false;
}
ContextOverlay.isInMarketplaceInspectionMode = false;
if (onInspectionCertificateScreen) {
setCertificateInfo(contextOverlayEntity);
}
if (onCommerceScreen) {
WalletScriptingInterface.refreshWalletStatus();
} else {
if (onMarketplaceScreen) {
onMarketplaceOpen('marketplace cta');
}
ui.tablet.sendToQml({
method: 'inspectionCertificate_resetCert'
});
off();
}
if (onMarketplaceItemTesterScreen) {
// Why setTimeout? The QML event bridge, wired above, requires a
// variable amount of time to come up, in practice less than
// 750ms.
Script.setTimeout(pushResourceObjectsInTest, 750);
}
console.debug(ui.buttonName + " app reports: Tablet screen changed.\nNew screen type: " + type +
"\nNew screen URL: " + url + "\nCurrent app open status: " + ui.isOpen + "\n");
};
var BUTTON_NAME = "MARKET";
var ui;
function startup() {
ui = new AppUi({
buttonName: BUTTON_NAME,
sortOrder: 9,
home: MARKETPLACE_QML_PATH,
onScreenChanged: onTabletScreenChanged,
onMessage: onQmlMessageReceived
});
ContextOverlay.contextOverlayClicked.connect(openInspectionCertificateQML);
Entities.canWriteAssetsChanged.connect(onCanWriteAssetsChanged);
GlobalServices.myUsernameChanged.connect(onUsernameChanged);
ui.tablet.webEventReceived.connect(onWebEventReceived);
WalletScriptingInterface.walletStatusChanged.connect(sendCommerceSettings);
Window.messageBoxClosed.connect(onMessageBoxClosed);
ResourceRequestObserver.resourceRequestEvent.connect(onResourceRequestEvent);
WalletScriptingInterface.refreshWalletStatus();
}
function off() {
}
function shutdown() {
maybeEnableHMDPreview();
Window.messageBoxClosed.disconnect(onMessageBoxClosed);
WalletScriptingInterface.walletStatusChanged.disconnect(sendCommerceSettings);
ui.tablet.webEventReceived.disconnect(onWebEventReceived);
GlobalServices.myUsernameChanged.disconnect(onUsernameChanged);
Entities.canWriteAssetsChanged.disconnect(onCanWriteAssetsChanged);
ContextOverlay.contextOverlayClicked.disconnect(openInspectionCertificateQML);
ResourceRequestObserver.resourceRequestEvent.disconnect(onResourceRequestEvent);
off();
}
//
// Run the functions.
//
startup();
Script.scriptEnding.connect(shutdown);
}()); // END LOCAL_SCOPE