mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-08 08:43:40 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into account-managed-wallet-punchlist2
This commit is contained in:
commit
7616639a40
14 changed files with 343 additions and 227 deletions
57
interface/resources/icons/tablet-icons/goto-a-msg.svg
Normal file
57
interface/resources/icons/tablet-icons/goto-a-msg.svg
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 50 50"
|
||||
style="enable-background:new 0 0 50 50;"
|
||||
xml:space="preserve"
|
||||
id="svg2"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="goto-a.svg"><metadata
|
||||
id="metadata14"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs12" /><sodipodi:namedview
|
||||
pagecolor="#ff0000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="852"
|
||||
inkscape:window-height="480"
|
||||
id="namedview10"
|
||||
showgrid="false"
|
||||
inkscape:zoom="4.72"
|
||||
inkscape:cx="25"
|
||||
inkscape:cy="25"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg2" /><style
|
||||
type="text/css"
|
||||
id="style4">
|
||||
.st0{fill:#FFFFFF;}
|
||||
.st1{fill:#EF3B4E;}
|
||||
</style>
|
||||
<circle class="st1" cx="44.1" cy="6" r="5.6"/>
|
||||
<g
|
||||
id="Layer_2" /><g
|
||||
id="Layer_1"
|
||||
style="fill:#000000;fill-opacity:1"><path
|
||||
class="st0"
|
||||
d="M47.2,41.3l-9.1-9.1c-0.8-0.8-1.9-1.1-3-1l-2.4-2.4c1.8-2.6,2.8-5.7,2.8-9c0-8.9-7.2-16.1-16.1-16.1 S3.3,11,3.3,19.8c0,8.9,7.2,16.1,16.1,16.1c4.1,0,7.8-1.5,10.6-4l2.2,2.2c-0.2,1.1,0.1,2.2,1,3l9.1,9.1c1.4,1.4,3.6,1.4,4.9,0 C48.5,44.9,48.5,42.7,47.2,41.3z M19.4,32.2c-6.8,0-12.3-5.5-12.3-12.3c0-6.8,5.5-12.3,12.3-12.3s12.3,5.5,12.3,12.3 C31.8,26.6,26.2,32.2,19.4,32.2z"
|
||||
id="path8"
|
||||
style="fill:#000000;fill-opacity:1" /></g></svg>
|
After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 911 B After Width: | Height: | Size: 911 B |
6
interface/resources/icons/tablet-icons/wallet-a-msg.svg
Normal file
6
interface/resources/icons/tablet-icons/wallet-a-msg.svg
Normal file
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st1{fill:#EF3B4E;}
|
||||
</style>
|
||||
<circle class="st1" cx="84.6" cy="11.5" r="10.75"/>
|
||||
<g><path d="M2.4,70.5c0,6.1,4.9,11,11,11H76c6.1,0,11-4.9,11-11V59.6c3.7-0.7,6.6-3.9,6.6-7.9v-7.5c0-3.9-2.8-7.2-6.6-7.9V25.5 c0-6.1-4.9-11-11-11H13.4c-6.1,0-11,4.9-11,11V70.5z M87.6,51.8c0,1.1-0.9,2-2,2H72.2c-2.8,0-5-2.2-5-5v-1.5c0-2.8,2.2-5,5-5h13.3 c1.1,0,2,0.9,2,2V51.8z M8.4,25.5c0-2.8,2.2-5,5-5H76c2.8,0,5,2.2,5,5v10.7h-8.7c-6.1,0-11,4.9-11,11v1.5c0,6.1,4.9,11,11,11H81 v10.7c0,2.8-2.2,5-5,5H13.4c-2.8,0-5-2.2-5-5V25.5z"></path></g></svg>
|
After Width: | Height: | Size: 755 B |
16
interface/resources/icons/tablet-icons/wallet-i-msg.svg
Normal file
16
interface/resources/icons/tablet-icons/wallet-i-msg.svg
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
.st1{fill:#EF3B4E;}
|
||||
</style>
|
||||
<circle class="st1" cx="84.6" cy="11.5" r="10.75"/>
|
||||
<g>
|
||||
<path class="st0" d="M2.4,70.5c0,6.1,4.9,11,11,11H76c6.1,0,11-4.9,11-11V59.6c3.7-0.7,6.6-3.9,6.6-7.9v-7.5c0-3.9-2.8-7.2-6.6-7.9
|
||||
V25.5c0-6.1-4.9-11-11-11H13.4c-6.1,0-11,4.9-11,11C2.4,25.5,2.4,70.5,2.4,70.5z M87.6,51.8c0,1.1-0.9,2-2,2H72.2c-2.8,0-5-2.2-5-5
|
||||
v-1.5c0-2.8,2.2-5,5-5h13.3c1.1,0,2,0.9,2,2L87.6,51.8L87.6,51.8z M8.4,25.5c0-2.8,2.2-5,5-5H76c2.8,0,5,2.2,5,5v10.7h-8.7
|
||||
c-6.1,0-11,4.9-11,11v1.5c0,6.1,4.9,11,11,11H81v10.7c0,2.8-2.2,5-5,5H13.4c-2.8,0-5-2.2-5-5V25.5z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 984 B |
|
@ -93,7 +93,7 @@ Rectangle {
|
|||
console.log("Failed to get Available Updates", result.data.message);
|
||||
} else {
|
||||
sendToScript({method: 'purchases_availableUpdatesReceived', numUpdates: result.data.updates.length });
|
||||
root.numUpdatesAvailable = result.data.updates.length;
|
||||
root.numUpdatesAvailable = result.total_entries;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,14 +45,6 @@ Item {
|
|||
onHistoryResult : {
|
||||
transactionHistoryModel.handlePage(null, result);
|
||||
}
|
||||
|
||||
onAvailableUpdatesResult: {
|
||||
if (result.status !== 'success') {
|
||||
console.log("Failed to get Available Updates", result.data.message);
|
||||
} else {
|
||||
sendToScript({method: 'wallet_availableUpdatesReceived', numUpdates: result.data.updates.length });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
|
|
@ -116,6 +116,7 @@ MyAvatar::MyAvatar(QThread* thread) :
|
|||
_bodySensorMatrix(),
|
||||
_goToPending(false),
|
||||
_goToSafe(true),
|
||||
_goToFeetAjustment(false),
|
||||
_goToPosition(),
|
||||
_goToOrientation(),
|
||||
_prevShouldDrawHead(true),
|
||||
|
@ -498,7 +499,7 @@ void MyAvatar::update(float deltaTime) {
|
|||
setCurrentStandingHeight(computeStandingHeightMode(getControllerPoseInAvatarFrame(controller::Action::HEAD)));
|
||||
setAverageHeadRotation(computeAverageHeadRotation(getControllerPoseInAvatarFrame(controller::Action::HEAD)));
|
||||
|
||||
if (_drawAverageFacingEnabled) {
|
||||
if (_drawAverageFacingEnabled) {
|
||||
auto sensorHeadPose = getControllerPoseInSensorFrame(controller::Action::HEAD);
|
||||
glm::vec3 worldHeadPos = transformPoint(getSensorToWorldMatrix(), sensorHeadPose.getTranslation());
|
||||
glm::vec3 worldFacingAverage = transformVectorFast(getSensorToWorldMatrix(), glm::vec3(_headControllerFacingMovingAverage.x, 0.0f, _headControllerFacingMovingAverage.y));
|
||||
|
@ -526,6 +527,11 @@ void MyAvatar::update(float deltaTime) {
|
|||
_physicsSafetyPending = getCollisionsEnabled();
|
||||
_characterController.recomputeFlying(); // In case we've gone to into the sky.
|
||||
}
|
||||
if (_goToFeetAjustment && _skeletonModelLoaded) {
|
||||
auto feetAjustment = getWorldPosition() - getWorldFeetPosition();
|
||||
goToLocation(getWorldPosition() + feetAjustment);
|
||||
_goToFeetAjustment = false;
|
||||
}
|
||||
if (_physicsSafetyPending && qApp->isPhysicsEnabled() && _characterController.isEnabledAndReady()) {
|
||||
// When needed and ready, arrange to check and fix.
|
||||
_physicsSafetyPending = false;
|
||||
|
@ -1728,6 +1734,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
|||
|
||||
_headBoneSet.clear();
|
||||
_cauterizationNeedsUpdate = true;
|
||||
_skeletonModelLoaded = false;
|
||||
|
||||
std::shared_ptr<QMetaObject::Connection> skeletonConnection = std::make_shared<QMetaObject::Connection>();
|
||||
*skeletonConnection = QObject::connect(_skeletonModel.get(), &SkeletonModel::skeletonLoaded, [this, skeletonModelChangeCount, skeletonConnection]() {
|
||||
|
@ -1745,6 +1752,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
|||
_skeletonModel->setCauterizeBoneSet(_headBoneSet);
|
||||
_fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl();
|
||||
initAnimGraph();
|
||||
_skeletonModelLoaded = true;
|
||||
}
|
||||
QObject::disconnect(*skeletonConnection);
|
||||
});
|
||||
|
@ -2945,46 +2953,10 @@ void MyAvatar::goToLocation(const QVariant& propertiesVar) {
|
|||
}
|
||||
|
||||
void MyAvatar::goToFeetLocation(const glm::vec3& newPosition,
|
||||
bool hasOrientation, const glm::quat& newOrientation,
|
||||
bool shouldFaceLocation) {
|
||||
|
||||
qCDebug(interfaceapp).nospace() << "MyAvatar goToFeetLocation - moving to " << newPosition.x << ", "
|
||||
<< newPosition.y << ", " << newPosition.z;
|
||||
|
||||
ShapeInfo shapeInfo;
|
||||
computeShapeInfo(shapeInfo);
|
||||
glm::vec3 halfExtents = shapeInfo.getHalfExtents();
|
||||
glm::vec3 localFeetPos = shapeInfo.getOffset() - glm::vec3(0.0f, halfExtents.y + halfExtents.x, 0.0f);
|
||||
glm::mat4 localFeet = createMatFromQuatAndPos(Quaternions::IDENTITY, localFeetPos);
|
||||
|
||||
glm::mat4 worldFeet = createMatFromQuatAndPos(Quaternions::IDENTITY, newPosition);
|
||||
|
||||
glm::mat4 avatarMat = worldFeet * glm::inverse(localFeet);
|
||||
|
||||
glm::vec3 adjustedPosition = extractTranslation(avatarMat);
|
||||
|
||||
_goToPending = true;
|
||||
_goToPosition = adjustedPosition;
|
||||
_goToOrientation = getWorldOrientation();
|
||||
if (hasOrientation) {
|
||||
qCDebug(interfaceapp).nospace() << "MyAvatar goToFeetLocation - new orientation is "
|
||||
<< newOrientation.x << ", " << newOrientation.y << ", " << newOrientation.z << ", " << newOrientation.w;
|
||||
|
||||
// orient the user to face the target
|
||||
glm::quat quatOrientation = cancelOutRollAndPitch(newOrientation);
|
||||
|
||||
if (shouldFaceLocation) {
|
||||
quatOrientation = newOrientation * glm::angleAxis(PI, Vectors::UP);
|
||||
|
||||
// move the user a couple units away
|
||||
const float DISTANCE_TO_USER = 2.0f;
|
||||
_goToPosition = adjustedPosition - quatOrientation * IDENTITY_FORWARD * DISTANCE_TO_USER;
|
||||
}
|
||||
|
||||
_goToOrientation = quatOrientation;
|
||||
}
|
||||
|
||||
emit transformChanged();
|
||||
bool hasOrientation, const glm::quat& newOrientation,
|
||||
bool shouldFaceLocation) {
|
||||
_goToFeetAjustment = true;
|
||||
goToLocation(newPosition, hasOrientation, newOrientation, shouldFaceLocation);
|
||||
}
|
||||
|
||||
void MyAvatar::goToLocation(const glm::vec3& newPosition,
|
||||
|
|
|
@ -1732,6 +1732,7 @@ private:
|
|||
bool _goToPending { false };
|
||||
bool _physicsSafetyPending { false };
|
||||
bool _goToSafe { true };
|
||||
bool _goToFeetAjustment { false };
|
||||
glm::vec3 _goToPosition;
|
||||
glm::quat _goToOrientation;
|
||||
|
||||
|
@ -1807,6 +1808,7 @@ private:
|
|||
|
||||
bool _haveReceivedHeightLimitsFromDomain { false };
|
||||
int _disableHandTouchCount { 0 };
|
||||
bool _skeletonModelLoaded { false };
|
||||
|
||||
Setting::Handle<QString> _dominantHandSetting;
|
||||
Setting::Handle<float> _headPitchSetting;
|
||||
|
|
|
@ -106,7 +106,9 @@ function AppUi(properties) {
|
|||
that.notificationPollCaresAboutSince = false;
|
||||
that.notificationInitialCallbackMade = false;
|
||||
that.notificationDisplayBanner = function (message) {
|
||||
Window.displayAnnouncement(message);
|
||||
if (!that.isOpen) {
|
||||
Window.displayAnnouncement(message);
|
||||
}
|
||||
};
|
||||
//
|
||||
// END Notification Handling Defaults
|
||||
|
@ -117,6 +119,7 @@ function AppUi(properties) {
|
|||
// Set isOpen, wireEventBridge, set buttonActive as appropriate,
|
||||
// and finally call onOpened() or onClosed() IFF defined.
|
||||
that.setCurrentVisibleScreenMetadata(type, url);
|
||||
|
||||
if (that.checkIsOpen(type, url)) {
|
||||
that.wireEventBridge(true);
|
||||
if (!that.isOpen) {
|
||||
|
@ -154,17 +157,21 @@ function AppUi(properties) {
|
|||
return;
|
||||
}
|
||||
|
||||
// User is "appearing offline"
|
||||
if (GlobalServices.findableBy === "none") {
|
||||
// User is "appearing offline" or is offline
|
||||
if (GlobalServices.findableBy === "none" || Account.username === "") {
|
||||
that.notificationPollTimeout = Script.setTimeout(that.notificationPoll, that.notificationPollTimeoutMs);
|
||||
return;
|
||||
}
|
||||
|
||||
var url = METAVERSE_BASE + that.notificationPollEndpoint;
|
||||
|
||||
var settingsKey = "notifications/" + that.buttonName + "/lastPoll";
|
||||
var currentTimestamp = new Date().getTime();
|
||||
var lastPollTimestamp = Settings.getValue(settingsKey, currentTimestamp);
|
||||
if (that.notificationPollCaresAboutSince) {
|
||||
url = url + "&since=" + (new Date().getTime());
|
||||
url = url + "&since=" + lastPollTimestamp/1000;
|
||||
}
|
||||
Settings.setValue(settingsKey, currentTimestamp);
|
||||
|
||||
console.debug(that.buttonName, 'polling for notifications at endpoint', url);
|
||||
|
||||
|
@ -192,17 +199,18 @@ function AppUi(properties) {
|
|||
} else {
|
||||
concatenatedServerResponse = concatenatedServerResponse.concat(that.notificationDataProcessPage(response));
|
||||
currentDataPageToRetrieve++;
|
||||
request({ uri: (url + "&page=" + currentDataPageToRetrieve) }, requestCallback);
|
||||
request({ json: true, uri: (url + "&page=" + currentDataPageToRetrieve) }, requestCallback);
|
||||
}
|
||||
}
|
||||
|
||||
request({ uri: url }, requestCallback);
|
||||
request({ json: true, uri: url }, requestCallback);
|
||||
};
|
||||
|
||||
// This won't do anything if there isn't a notification endpoint set
|
||||
that.notificationPoll();
|
||||
|
||||
function availabilityChanged() {
|
||||
function restartNotificationPoll() {
|
||||
that.notificationInitialCallbackMade = false;
|
||||
if (that.notificationPollTimeout) {
|
||||
Script.clearTimeout(that.notificationPollTimeout);
|
||||
that.notificationPollTimeout = false;
|
||||
|
@ -302,7 +310,8 @@ function AppUi(properties) {
|
|||
} : that.ignore;
|
||||
that.onScriptEnding = function onScriptEnding() {
|
||||
// Close if necessary, clean up any remaining handlers, and remove the button.
|
||||
GlobalServices.findableByChanged.disconnect(availabilityChanged);
|
||||
GlobalServices.myUsernameChanged.disconnect(restartNotificationPoll);
|
||||
GlobalServices.findableByChanged.disconnect(restartNotificationPoll);
|
||||
if (that.isOpen) {
|
||||
that.close();
|
||||
}
|
||||
|
@ -322,6 +331,7 @@ function AppUi(properties) {
|
|||
that.tablet.screenChanged.connect(that.onScreenChanged);
|
||||
that.button.clicked.connect(that.onClicked);
|
||||
Script.scriptEnding.connect(that.onScriptEnding);
|
||||
GlobalServices.findableByChanged.connect(availabilityChanged);
|
||||
GlobalServices.findableByChanged.connect(restartNotificationPoll);
|
||||
GlobalServices.myUsernameChanged.connect(restartNotificationPoll);
|
||||
}
|
||||
module.exports = AppUi;
|
||||
|
|
|
@ -19,7 +19,7 @@ module.exports = {
|
|||
|
||||
// ------------------------------------------------------------------
|
||||
request: function (options, callback) { // cb(error, responseOfCorrectContentType) of url. A subset of npm request.
|
||||
var httpRequest = new XMLHttpRequest(), key;
|
||||
var httpRequest = new XMLHttpRequest(), key;
|
||||
// QT bug: apparently doesn't handle onload. Workaround using readyState.
|
||||
httpRequest.onreadystatechange = function () {
|
||||
var READY_STATE_DONE = 4;
|
||||
|
@ -72,7 +72,7 @@ module.exports = {
|
|||
}
|
||||
httpRequest.open(options.method, options.uri, true);
|
||||
httpRequest.send(options.body || null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ===========================================================================================
|
||||
|
|
|
@ -474,9 +474,6 @@ function fromQml(message) {
|
|||
Window.location = "hifi://BankOfHighFidelity";
|
||||
}
|
||||
break;
|
||||
case 'wallet_availableUpdatesReceived':
|
||||
// NOP
|
||||
break;
|
||||
case 'http.request':
|
||||
// Handled elsewhere, don't log.
|
||||
break;
|
||||
|
@ -491,32 +488,65 @@ function walletOpened() {
|
|||
Controller.mouseMoveEvent.connect(handleMouseMoveEvent);
|
||||
triggerMapping.enable();
|
||||
triggerPressMapping.enable();
|
||||
shouldShowDot = false;
|
||||
ui.messagesWaiting(shouldShowDot);
|
||||
}
|
||||
|
||||
function walletClosed() {
|
||||
off();
|
||||
}
|
||||
|
||||
//
|
||||
// Manage the connection between the button and the window.
|
||||
//
|
||||
function notificationDataProcessPage(data) {
|
||||
return data.data.history;
|
||||
}
|
||||
|
||||
var shouldShowDot = false;
|
||||
function notificationPollCallback(historyArray) {
|
||||
if (!ui.isOpen) {
|
||||
var notificationCount = historyArray.length;
|
||||
shouldShowDot = shouldShowDot || notificationCount > 0;
|
||||
ui.messagesWaiting(shouldShowDot);
|
||||
|
||||
if (notificationCount > 0) {
|
||||
var message;
|
||||
if (!ui.notificationInitialCallbackMade) {
|
||||
message = "You have " + notificationCount + " unread wallet " +
|
||||
"transaction" + (notificationCount === 1 ? "" : "s") + ". Open WALLET to see all activity.";
|
||||
ui.notificationDisplayBanner(message);
|
||||
} else {
|
||||
for (var i = 0; i < notificationCount; i++) {
|
||||
message = '"' + (historyArray[i].message) + '" ' +
|
||||
"Open WALLET to see all activity.";
|
||||
ui.notificationDisplayBanner(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isReturnedDataEmpty(data) {
|
||||
var historyArray = data.data.history;
|
||||
return historyArray.length === 0;
|
||||
}
|
||||
|
||||
var DEVELOPER_MENU = "Developer";
|
||||
var MARKETPLACE_ITEM_TESTER_LABEL = "Marketplace Item Tester";
|
||||
var MARKETPLACE_ITEM_TESTER_QML_SOURCE = "hifi/commerce/marketplaceItemTester/MarketplaceItemTester.qml";
|
||||
function installMarketplaceItemTester() {
|
||||
if (!Menu.menuExists(DEVELOPER_MENU)) {
|
||||
Menu.addMenu(DEVELOPER_MENU);
|
||||
Menu.addMenu(DEVELOPER_MENU);
|
||||
}
|
||||
if (!Menu.menuItemExists(DEVELOPER_MENU, MARKETPLACE_ITEM_TESTER_LABEL)) {
|
||||
Menu.addMenuItem({ menuName: DEVELOPER_MENU,
|
||||
menuItemName: MARKETPLACE_ITEM_TESTER_LABEL,
|
||||
isCheckable: false })
|
||||
Menu.addMenuItem({
|
||||
menuName: DEVELOPER_MENU,
|
||||
menuItemName: MARKETPLACE_ITEM_TESTER_LABEL,
|
||||
isCheckable: false
|
||||
});
|
||||
}
|
||||
|
||||
Menu.menuItemEvent.connect(function (menuItem) {
|
||||
if (menuItem === MARKETPLACE_ITEM_TESTER_LABEL) {
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.loadQMLSource(MARKETPLACE_ITEM_TESTER_QML_SOURCE);
|
||||
ui.open(MARKETPLACE_ITEM_TESTER_QML_SOURCE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -539,7 +569,13 @@ function startup() {
|
|||
home: WALLET_QML_SOURCE,
|
||||
onOpened: walletOpened,
|
||||
onClosed: walletClosed,
|
||||
onMessage: fromQml
|
||||
onMessage: fromQml,
|
||||
notificationPollEndpoint: "/api/v1/commerce/history?per_page=10",
|
||||
notificationPollTimeoutMs: 300000,
|
||||
notificationDataProcessPage: notificationDataProcessPage,
|
||||
notificationPollCallback: notificationPollCallback,
|
||||
notificationPollStopPaginatingConditionMet: isReturnedDataEmpty,
|
||||
notificationPollCaresAboutSince: true
|
||||
});
|
||||
GlobalServices.myUsernameChanged.connect(onUsernameChanged);
|
||||
installMarketplaceItemTester();
|
||||
|
|
|
@ -178,10 +178,10 @@ function onUsernameChanged() {
|
|||
}
|
||||
}
|
||||
|
||||
var userHasUpdates = false;
|
||||
function walletNeedsSetup() {
|
||||
return Wallet.walletStatus === 1;
|
||||
}
|
||||
|
||||
function sendCommerceSettings() {
|
||||
ui.sendToHtml({
|
||||
type: "marketplaces",
|
||||
|
@ -191,7 +191,7 @@ function sendCommerceSettings() {
|
|||
userIsLoggedIn: Account.loggedIn,
|
||||
walletNeedsSetup: walletNeedsSetup(),
|
||||
metaverseServerURL: Account.metaverseServerURL,
|
||||
messagesWaiting: userHasUpdates
|
||||
messagesWaiting: shouldShowDot
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -972,10 +972,9 @@ var onQmlMessageReceived = function onQmlMessageReceived(message) {
|
|||
removeOverlays();
|
||||
}
|
||||
break;
|
||||
case 'wallet_availableUpdatesReceived':
|
||||
case 'purchases_availableUpdatesReceived':
|
||||
userHasUpdates = message.numUpdates > 0;
|
||||
ui.messagesWaiting(userHasUpdates);
|
||||
shouldShowDot = message.numUpdates > 0;
|
||||
ui.messagesWaiting(shouldShowDot && !ui.isOpen);
|
||||
break;
|
||||
case 'purchases_updateWearables':
|
||||
var currentlyWornWearables = [];
|
||||
|
@ -1131,9 +1130,41 @@ var onTabletScreenChanged = function onTabletScreenChanged(type, url) {
|
|||
"\nNew screen URL: " + url + "\nCurrent app open status: " + ui.isOpen + "\n");
|
||||
};
|
||||
|
||||
//
|
||||
// Manage the connection between the button and the window.
|
||||
//
|
||||
function notificationDataProcessPage(data) {
|
||||
return data.data.updates;
|
||||
}
|
||||
|
||||
var shouldShowDot = false;
|
||||
function notificationPollCallback(updatesArray) {
|
||||
shouldShowDot = shouldShowDot || updatesArray.length > 0;
|
||||
ui.messagesWaiting(shouldShowDot && !ui.isOpen);
|
||||
|
||||
if (updatesArray.length > 0) {
|
||||
var message;
|
||||
if (!ui.notificationInitialCallbackMade) {
|
||||
message = updatesArray.length + " of your purchased items " +
|
||||
(updatesArray.length === 1 ? "has an update " : "have updates ") +
|
||||
"available. Open MARKET to update.";
|
||||
ui.notificationDisplayBanner(message);
|
||||
|
||||
ui.notificationPollCaresAboutSince = true;
|
||||
} else {
|
||||
for (var i = 0; i < updatesArray.length; i++) {
|
||||
message = "Update available for \"" +
|
||||
updatesArray[i].base_item_title + "\"." +
|
||||
"Open MARKET to update.";
|
||||
ui.notificationDisplayBanner(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isReturnedDataEmpty(data) {
|
||||
var historyArray = data.data.updates;
|
||||
return historyArray.length === 0;
|
||||
}
|
||||
|
||||
|
||||
var BUTTON_NAME = "MARKET";
|
||||
var MARKETPLACE_URL = METAVERSE_SERVER_URL + "/marketplace";
|
||||
var MARKETPLACE_URL_INITIAL = MARKETPLACE_URL + "?"; // Append "?" to signal injected script that it's the initial page.
|
||||
|
@ -1145,7 +1176,13 @@ function startup() {
|
|||
inject: MARKETPLACES_INJECT_SCRIPT_URL,
|
||||
home: MARKETPLACE_URL_INITIAL,
|
||||
onScreenChanged: onTabletScreenChanged,
|
||||
onMessage: onQmlMessageReceived
|
||||
onMessage: onQmlMessageReceived,
|
||||
notificationPollEndpoint: "/api/v1/commerce/available_updates?per_page=10",
|
||||
notificationPollTimeoutMs: 300000,
|
||||
notificationDataProcessPage: notificationDataProcessPage,
|
||||
notificationPollCallback: notificationPollCallback,
|
||||
notificationPollStopPaginatingConditionMet: isReturnedDataEmpty,
|
||||
notificationPollCaresAboutSince: false // Changes to true after first poll
|
||||
});
|
||||
ContextOverlay.contextOverlayClicked.connect(openInspectionCertificateQML);
|
||||
Entities.canWriteAssetsChanged.connect(onCanWriteAssetsChanged);
|
||||
|
|
|
@ -823,46 +823,40 @@ function notificationDataProcessPage(data) {
|
|||
}
|
||||
|
||||
var shouldShowDot = false;
|
||||
var storedOnlineUsersArray = [];
|
||||
var pingPong = false;
|
||||
var storedOnlineUsers = {};
|
||||
function notificationPollCallback(connectionsArray) {
|
||||
//
|
||||
// START logic for handling online/offline user changes
|
||||
//
|
||||
var i, j;
|
||||
var newlyOnlineConnectionsArray = [];
|
||||
for (i = 0; i < connectionsArray.length; i++) {
|
||||
var currentUser = connectionsArray[i];
|
||||
pingPong = !pingPong;
|
||||
var newOnlineUsers = 0;
|
||||
var message;
|
||||
|
||||
if (connectionsArray[i].online) {
|
||||
var indexOfStoredOnlineUser = -1;
|
||||
for (j = 0; j < storedOnlineUsersArray.length; j++) {
|
||||
if (currentUser.username === storedOnlineUsersArray[j].username) {
|
||||
indexOfStoredOnlineUser = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If the user record isn't already presesnt inside `storedOnlineUsersArray`...
|
||||
if (indexOfStoredOnlineUser < 0) {
|
||||
storedOnlineUsersArray.push(currentUser);
|
||||
newlyOnlineConnectionsArray.push(currentUser);
|
||||
}
|
||||
} else {
|
||||
var indexOfOfflineUser = -1;
|
||||
for (j = 0; j < storedOnlineUsersArray.length; j++) {
|
||||
if (currentUser.username === storedOnlineUsersArray[j].username) {
|
||||
indexOfOfflineUser = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (indexOfOfflineUser >= 0) {
|
||||
storedOnlineUsersArray.splice(indexOfOfflineUser);
|
||||
}
|
||||
connectionsArray.forEach(function (user) {
|
||||
var stored = storedOnlineUsers[user.username];
|
||||
var storedOrNew = stored || user;
|
||||
storedOrNew.pingPong = pingPong;
|
||||
if (stored) {
|
||||
return;
|
||||
}
|
||||
|
||||
newOnlineUsers++;
|
||||
storedOnlineUsers[user.username] = user;
|
||||
|
||||
if (!ui.isOpen && ui.notificationInitialCallbackMade) {
|
||||
message = user.username + " is available in " +
|
||||
user.location.root.name + ". Open PEOPLE to join them.";
|
||||
ui.notificationDisplayBanner(message);
|
||||
}
|
||||
});
|
||||
var key;
|
||||
for (key in storedOnlineUsers) {
|
||||
if (storedOnlineUsers[key].pingPong !== pingPong) {
|
||||
delete storedOnlineUsers[key];
|
||||
}
|
||||
}
|
||||
// If there's new data, the light should turn on.
|
||||
// If the light is already on and you have connections online, the light should stay on.
|
||||
// In all other cases, the light should turn off or stay off.
|
||||
shouldShowDot = newlyOnlineConnectionsArray.length > 0 || (storedOnlineUsersArray.length > 0 && shouldShowDot);
|
||||
shouldShowDot = newOnlineUsers > 0 || (Object.keys(storedOnlineUsers).length > 0 && shouldShowDot);
|
||||
//
|
||||
// END logic for handling online/offline user changes
|
||||
//
|
||||
|
@ -874,19 +868,10 @@ function notificationPollCallback(connectionsArray) {
|
|||
shouldShowDot: shouldShowDot
|
||||
});
|
||||
|
||||
if (newlyOnlineConnectionsArray.length > 0) {
|
||||
var message;
|
||||
if (!ui.notificationInitialCallbackMade) {
|
||||
message = newlyOnlineConnectionsArray.length + " of your connections " +
|
||||
(newlyOnlineConnectionsArray.length === 1 ? "is" : "are") + " online. Open PEOPLE to join them!";
|
||||
ui.notificationDisplayBanner(message);
|
||||
} else {
|
||||
for (i = 0; i < newlyOnlineConnectionsArray.length; i++) {
|
||||
message = newlyOnlineConnectionsArray[i].username + " is available in " +
|
||||
newlyOnlineConnectionsArray[i].location.root.name + ". Open PEOPLE to join them!";
|
||||
ui.notificationDisplayBanner(message);
|
||||
}
|
||||
}
|
||||
if (newOnlineUsers > 0 && !ui.notificationInitialCallbackMade) {
|
||||
message = newOnlineUsers + " of your connections " +
|
||||
(newOnlineUsers === 1 ? "is" : "are") + " available online. Open PEOPLE to join them.";
|
||||
ui.notificationDisplayBanner(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -904,7 +889,7 @@ function startup() {
|
|||
onOpened: palOpened,
|
||||
onClosed: off,
|
||||
onMessage: fromQml,
|
||||
notificationPollEndpoint: "/api/v1/users?filter=connections&per_page=10",
|
||||
notificationPollEndpoint: "/api/v1/users?filter=connections&status=online&per_page=10",
|
||||
notificationPollTimeoutMs: 60000,
|
||||
notificationDataProcessPage: notificationDataProcessPage,
|
||||
notificationPollCallback: notificationPollCallback,
|
||||
|
|
|
@ -15,118 +15,121 @@
|
|||
//
|
||||
|
||||
(function () { // BEGIN LOCAL_SCOPE
|
||||
var request = Script.require('request').request;
|
||||
var AppUi = Script.require('appUi');
|
||||
var DEBUG = false;
|
||||
function debug() {
|
||||
if (!DEBUG) {
|
||||
return;
|
||||
}
|
||||
print('tablet-goto.js:', [].map.call(arguments, JSON.stringify));
|
||||
}
|
||||
|
||||
var stories = {}, pingPong = false;
|
||||
function expire(id) {
|
||||
var options = {
|
||||
uri: Account.metaverseServerURL + '/api/v1/user_stories/' + id,
|
||||
method: 'PUT',
|
||||
json: true,
|
||||
body: {expire: "true"}
|
||||
};
|
||||
request(options, function (error, response) {
|
||||
debug('expired story', options, 'error:', error, 'response:', response);
|
||||
if (error || (response.status !== 'success')) {
|
||||
print("ERROR expiring story: ", error || response.status);
|
||||
}
|
||||
});
|
||||
}
|
||||
var PER_PAGE_DEBUG = 10;
|
||||
var PER_PAGE_NORMAL = 100;
|
||||
function pollForAnnouncements() {
|
||||
// We could bail now if !Account.isLoggedIn(), but what if we someday have system-wide announcments?
|
||||
var actions = 'announcement';
|
||||
var count = DEBUG ? PER_PAGE_DEBUG : PER_PAGE_NORMAL;
|
||||
var options = [
|
||||
'now=' + new Date().toISOString(),
|
||||
'include_actions=' + actions,
|
||||
'restriction=' + (Account.isLoggedIn() ? 'open,hifi' : 'open'),
|
||||
'require_online=true',
|
||||
'protocol=' + encodeURIComponent(Window.protocolSignature()),
|
||||
'per_page=' + count
|
||||
];
|
||||
var url = Account.metaverseServerURL + '/api/v1/user_stories?' + options.join('&');
|
||||
request({
|
||||
uri: url
|
||||
}, function (error, data) {
|
||||
debug(url, error, data);
|
||||
if (error || (data.status !== 'success')) {
|
||||
print("Error: unable to get", url, error || data.status);
|
||||
return;
|
||||
}
|
||||
var didNotify = false, key;
|
||||
pingPong = !pingPong;
|
||||
data.user_stories.forEach(function (story) {
|
||||
var stored = stories[story.id], storedOrNew = stored || story;
|
||||
debug('story exists:', !!stored, storedOrNew);
|
||||
if ((storedOrNew.username === Account.username) && (storedOrNew.place_name !== location.placename)) {
|
||||
if (storedOrNew.audience === 'for_connections') { // Only expire if we haven't already done so.
|
||||
expire(story.id);
|
||||
}
|
||||
return; // before marking
|
||||
}
|
||||
storedOrNew.pingPong = pingPong;
|
||||
if (stored) { // already seen
|
||||
return;
|
||||
}
|
||||
stories[story.id] = story;
|
||||
var message = story.username + " " + story.action_string + " in " +
|
||||
story.place_name + ". Open GOTO to join them.";
|
||||
Window.displayAnnouncement(message);
|
||||
didNotify = true;
|
||||
});
|
||||
for (key in stories) { // Any story we were tracking that was not marked, has expired.
|
||||
if (stories[key].pingPong !== pingPong) {
|
||||
debug('removing story', key);
|
||||
delete stories[key];
|
||||
}
|
||||
}
|
||||
if (didNotify) {
|
||||
ui.messagesWaiting(true);
|
||||
if (HMD.isHandControllerAvailable()) {
|
||||
var STRENGTH = 1.0, DURATION_MS = 60, HAND = 2; // both hands
|
||||
Controller.triggerHapticPulse(STRENGTH, DURATION_MS, HAND);
|
||||
}
|
||||
} else if (!Object.keys(stories).length) { // If there's nothing being tracked, then any messageWaiting has expired.
|
||||
ui.messagesWaiting(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
var MS_PER_SEC = 1000;
|
||||
var DEBUG_POLL_TIME_SEC = 10;
|
||||
var NORMAL_POLL_TIME_SEC = 60;
|
||||
var ANNOUNCEMENTS_POLL_TIME_MS = (DEBUG ? DEBUG_POLL_TIME_SEC : NORMAL_POLL_TIME_SEC) * MS_PER_SEC;
|
||||
var pollTimer = Script.setInterval(pollForAnnouncements, ANNOUNCEMENTS_POLL_TIME_MS);
|
||||
|
||||
function gotoOpened() {
|
||||
ui.messagesWaiting(false);
|
||||
shouldShowDot = false;
|
||||
ui.messagesWaiting(shouldShowDot);
|
||||
}
|
||||
|
||||
function notificationDataProcessPage(data) {
|
||||
return data.user_stories;
|
||||
}
|
||||
|
||||
var shouldShowDot = false;
|
||||
var pingPong = false;
|
||||
var storedAnnouncements = {};
|
||||
var storedFeaturedStories = {};
|
||||
var message;
|
||||
function notificationPollCallback(userStoriesArray) {
|
||||
//
|
||||
// START logic for keeping track of new info
|
||||
//
|
||||
pingPong = !pingPong;
|
||||
var totalNewStories = 0;
|
||||
var shouldNotifyIndividually = !ui.isOpen && ui.notificationInitialCallbackMade;
|
||||
userStoriesArray.forEach(function (story) {
|
||||
if (story.audience !== "for_connections" &&
|
||||
story.audience !== "for_feed") {
|
||||
return;
|
||||
}
|
||||
|
||||
var stored = storedAnnouncements[story.id] || storedFeaturedStories[story.id];
|
||||
var storedOrNew = stored || story;
|
||||
storedOrNew.pingPong = pingPong;
|
||||
if (stored) {
|
||||
return;
|
||||
}
|
||||
|
||||
totalNewStories++;
|
||||
|
||||
if (story.audience === "for_connections") {
|
||||
storedAnnouncements[story.id] = story;
|
||||
|
||||
if (shouldNotifyIndividually) {
|
||||
message = story.username + " says something is happening in " +
|
||||
story.place_name + ". Open GOTO to join them.";
|
||||
ui.notificationDisplayBanner(message);
|
||||
}
|
||||
} else if (story.audience === "for_feed") {
|
||||
storedFeaturedStories[story.id] = story;
|
||||
|
||||
if (shouldNotifyIndividually) {
|
||||
message = story.username + " invites you to an event in " +
|
||||
story.place_name + ". Open GOTO to join them.";
|
||||
ui.notificationDisplayBanner(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
var key;
|
||||
for (key in storedAnnouncements) {
|
||||
if (storedAnnouncements[key].pingPong !== pingPong) {
|
||||
delete storedAnnouncements[key];
|
||||
}
|
||||
}
|
||||
for (key in storedFeaturedStories) {
|
||||
if (storedFeaturedStories[key].pingPong !== pingPong) {
|
||||
delete storedFeaturedStories[key];
|
||||
}
|
||||
}
|
||||
//
|
||||
// END logic for keeping track of new info
|
||||
//
|
||||
|
||||
var totalStories = Object.keys(storedAnnouncements).length +
|
||||
Object.keys(storedFeaturedStories).length;
|
||||
shouldShowDot = totalNewStories > 0 || (totalStories > 0 && shouldShowDot);
|
||||
ui.messagesWaiting(shouldShowDot && !ui.isOpen);
|
||||
|
||||
if (totalStories > 0 && !ui.isOpen && !ui.notificationInitialCallbackMade) {
|
||||
message = "There " + (totalStories === 1 ? "is " : "are ") + totalStories + " event" +
|
||||
(totalStories === 1 ? "" : "s") + " to know about. " +
|
||||
"Open GOTO to see " + (totalStories === 1 ? "it" : "them") + ".";
|
||||
ui.notificationDisplayBanner(message);
|
||||
}
|
||||
}
|
||||
|
||||
function isReturnedDataEmpty(data) {
|
||||
var storiesArray = data.user_stories;
|
||||
return storiesArray.length === 0;
|
||||
}
|
||||
|
||||
var ui;
|
||||
var GOTO_QML_SOURCE = "hifi/tablet/TabletAddressDialog.qml";
|
||||
var BUTTON_NAME = "GOTO";
|
||||
function startup() {
|
||||
var options = [
|
||||
'include_actions=announcement',
|
||||
'restriction=open,hifi',
|
||||
'require_online=true',
|
||||
'protocol=' + encodeURIComponent(Window.protocolSignature()),
|
||||
'per_page=10'
|
||||
];
|
||||
var endpoint = '/api/v1/user_stories?' + options.join('&');
|
||||
|
||||
ui = new AppUi({
|
||||
buttonName: BUTTON_NAME,
|
||||
sortOrder: 8,
|
||||
onOpened: gotoOpened,
|
||||
home: GOTO_QML_SOURCE
|
||||
home: GOTO_QML_SOURCE,
|
||||
notificationPollEndpoint: endpoint,
|
||||
notificationPollTimeoutMs: 60000,
|
||||
notificationDataProcessPage: notificationDataProcessPage,
|
||||
notificationPollCallback: notificationPollCallback,
|
||||
notificationPollStopPaginatingConditionMet: isReturnedDataEmpty,
|
||||
notificationPollCaresAboutSince: false
|
||||
});
|
||||
}
|
||||
|
||||
function shutdown() {
|
||||
Script.clearInterval(pollTimer);
|
||||
}
|
||||
|
||||
startup();
|
||||
Script.scriptEnding.connect(shutdown);
|
||||
}()); // END LOCAL_SCOPE
|
||||
|
|
Loading…
Reference in a new issue