From 6e051b7431795c06402cee3161c9cd45c3dd6830 Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Thu, 20 Sep 2018 15:55:35 -0700 Subject: [PATCH] Checkpoint tray notifications * Fix app launch * refactor notifications code * fixup wording --- interface/src/commerce/QmlCommerce.cpp | 6 +- .../resources/tray-menu-notification.png | Bin 319 -> 319 bytes server-console/src/main.js | 2 +- server-console/src/modules/hf-acctinfo.js | 5 +- .../src/modules/hf-notifications.js | 449 +++++++++++------- 5 files changed, 277 insertions(+), 185 deletions(-) diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index e1f9f63bfb..8a77c078b9 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -49,11 +49,11 @@ QmlCommerce::QmlCommerce() { void QmlCommerce::openSystemApp(const QString& appPath) { - QUrl appUrl = PathUtils::qmlUrl(appPath); - auto tablet = dynamic_cast( DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system")); - tablet->loadQMLSource(appUrl); + tablet->loadQMLSource(appPath); + + DependencyManager::get()->openTablet(); } diff --git a/server-console/resources/tray-menu-notification.png b/server-console/resources/tray-menu-notification.png index 569ee95d7ed77761062251173dda4a02f2d40e75..0d6e15752ff20fe09ab20ace9cdc5e915af37c42 100644 GIT binary patch delta 150 zcmV;H0BQff0>1)~B!3xnMObuGZ)S9NVRB^vL1b@YWgtmyVP|DhWnpA_ami&o0000{ zNkl1)~B!2;OQb$4nuFf3k00004XF*Lt006O%3;baP00009a7bBm000id z000id0mpBsWB>pF)Ja4^R47v|PCIS_F%W%YEwD(TpaHswD{uiQlAeMFrGbWX(a>># zR5=0#X;UC1Hi<~K;A?EJCr?X8dY 0) { - text = this.data.sender_name + " sent you " + this.data.received_money + " HFC!"; - memo = "memo: \"" + this.data.message + "\" "; - } - else { - return; - } - } - else { - text = this.data.message.replace(/<\/?[^>]+(>|$)/g, ""); - } - message = memo + "Click to open WALLET."; + text = this.data.message.replace(/<\/?[^>]+(>|$)/g, ""); + message = "Click to open WALLET."; url = "hifiapp:hifi/commerce/wallet/Wallet.qml"; break; + case NotificationType.MARKETPLACE: if(typeof(this.data) == "number") { - text = this.data + " of your purchased items have updates available!"; + if (this.data == 1) { + text = this.data + " of your purchased items has an update available."; + } + else { + text = this.data + " of your purchased items have updates available."; + } } else { - text = "There's an update available for your version of " + this.data.base_item_title + "!"; + text = "Update available for " + this.data.base_item_title + "."; } - message = "Click to open MARKETPLACE."; + message = "Click to open MARKET."; url = "hifiapp:hifi/commerce/purchases/Purchases.qml"; break; } @@ -113,11 +126,15 @@ HifiNotification.prototype = { } } -function HifiNotifications(config, callback) { +function HifiNotifications(config, menuNotificationCallback) { this.config = config; - this.callback = callback; + this.menuNotificationCallback = menuNotificationCallback; this.onlineUsers = new Set([]); - this.since = new Date(this.config.get("notifySince", "1970-01-01T00:00:00.000Z")); + this.storiesSince = new Date(this.config.get("storiesNotifySince", "1970-01-01T00:00:00.000Z")); + this.peopleSince = new Date(this.config.get("peopleNotifySince", "1970-01-01T00:00:00.000Z")); + this.walletSince = new Date(this.config.get("walletNotifySince", "1970-01-01T00:00:00.000Z")); + this.marketplaceSince = new Date(this.config.get("marketplaceNotifySince", "1970-01-01T00:00:00.000Z")); + this.enable(this.enabled()); notifier.on('click', function(notifierObject, options) { StartInterface(options.url); @@ -129,35 +146,59 @@ HifiNotifications.prototype = { this.config.set("enableTrayNotifications", enabled); if(enabled) { var _this = this; - this.pollTimer = setInterval(function() { - var acctInfo = new AccountInfo(); - var token = acctInfo.accessToken(METAVERSE_SERVER_URL); - var _since = _this.since; - _this.since = new Date(); - IsInterfaceRunning(function(running) { - if(running) { - return; - } - _this.pollForStories(_since, token); - _this.pollForConnections(_since, token); - _this.pollForEconomicActivity(_since, token); - _this.pollForMarketplaceUpdates(_since, token); - }); + this.storiesPollTimer = setInterval(function() { + var _since = _this.storiesSince; + _this.storiesSince = new Date(); + _this.pollForStories(_since); }, - NOTIFICATION_POLL_TIME_MS); + STORIES_NOTIFICATION_POLL_TIME_MS); + + this.peoplePollTimer = setInterval(function() { + var _since = _this.peopleSince; + _this.peopleSince = new Date(); + _this.pollForConnections(_since); + }, + PEOPLE_NOTIFICATION_POLL_TIME_MS); + + this.walletPollTimer = setInterval(function() { + var _since = _this.walletSince; + _this.walletSince = new Date(); + _this.pollForEconomicActivity(_since); + }, + WALLET_NOTIFICATION_POLL_TIME_MS); + + this.marketplacePollTimer = setInterval(function() { + var _since = _this.marketplaceSince; + _this.marketplaceSince = new Date(); + _this.pollForMarketplaceUpdates(_since); + }, + MARKETPLACE_NOTIFICATION_POLL_TIME_MS); } - else if(this.pollTimer) { - clearInterval(this.pollTimer); + else { + if(this.storiesTimer) { + clearInterval(this.storiesTimer); + } + if(this.peoplePollTimer) { + clearInterval(this.peoplePollTimer); + } + if(this.walletPollTimer) { + clearInterval(this.walletPollTimer); + } + if(this.marketplacePollTimer) { + clearInterval(this.marketplacePollTimer); + } } }, enabled: function() { return this.config.get("enableTrayNotifications", true); }, stopPolling: function() { - this.config.set("notifySince", this.since.toISOString()); - if(this.pollTimer) { - clearInterval(this.pollTimer); - } + this.config.set("storiesNotifySince", this.storiesSince.toISOString()); + this.config.set("peopleNotifySince", this.peopleSince.toISOString()); + this.config.set("walletNotifySince", this.walletSince.toISOString()); + this.config.set("marketplaceNotifySince", this.marketplaceSince.toISOString()); + + this.enable(false); }, _pollToDisableHighlight: function(notifyType, error, data) { if (error || !data.body) { @@ -172,58 +213,81 @@ HifiNotifications.prototype = { } console.log(content); if(!content.total_entries) { - this.callback(notifyType, false); + this.menuNotificationCallback(notifyType, false); } }, - _pollCommon: function(notifyType, error, data, since) { - var maxNotificationItemCount = since.getTime() ? MAX_NOTIFICATION_ITEMS : STARTUP_MAX_NOTIFICATION_ITEMS; - if (error || !data.body) { - console.log("Error: unable to get " + url); - return false; - } - var content = JSON.parse(data.body); - if(!content || content.status != 'success') { - console.log("Error: unable to get " + url); - return false; - } - console.log(content); - if(!content.total_entries) { - return; - } - this.callback(notifyType, true); - if(content.total_entries >= maxNotificationItemCount) { - var notification = new HifiNotification(notifyType, content.total_entries); - notification.show(); - } - else { - var notifyData = [] - switch(notifyType) { - case NotificationType.GOTO: - notifyData = content.user_stories; - break; - case NotificationType.PEOPLE: - notifyData = content.data.users; - break; - case NotificationType.WALLET: - notifyData = content.data.history; - break; - case NotificationType.MARKETPLACE: - notifyData = content.data.updates; - break; - } + _pollCommon: function(notifyType, url, since, finished) { - notifyData.forEach(function(notifyDataEntry) { - var notification = new HifiNotification(notifyType, notifyDataEntry); - notification.show(); - }); - } - }, - pollForStories: function(since, token) { var _this = this; - var _token = token; + IsInterfaceRunning(function(running) { + if(running) { + finished(false); + return; + } + var acctInfo = new AccountInfo(); + var token = acctInfo.accessToken(METAVERSE_SERVER_URL); + if(!token) { + return; + } + request.get({ + uri: url, + 'auth': { + 'bearer': token + } + }, function (error, data) { + + var maxNotificationItemCount = since.getTime() ? MAX_NOTIFICATION_ITEMS : STARTUP_MAX_NOTIFICATION_ITEMS; + if (error || !data.body) { + console.log("Error: unable to get " + url); + finished(false); + return; + } + var content = JSON.parse(data.body); + if(!content || content.status != 'success') { + console.log("Error: unable to get " + url); + finished(false); + return; + } + console.log(content); + if(!content.total_entries) { + finished(true, token); + return; + } + _this.menuNotificationCallback(notifyType, true); + if(content.total_entries >= maxNotificationItemCount) { + var notification = new HifiNotification(notifyType, content.total_entries); + notification.show(); + } + else { + var notifyData = [] + switch(notifyType) { + case NotificationType.GOTO: + notifyData = content.user_stories; + break; + case NotificationType.PEOPLE: + notifyData = content.data.users; + break; + case NotificationType.WALLET: + notifyData = content.data.history; + break; + case NotificationType.MARKETPLACE: + notifyData = content.data.updates; + break; + } + + notifyData.forEach(function(notifyDataEntry) { + var notification = new HifiNotification(notifyType, notifyDataEntry); + notification.show(); + }); + } + finished(true, token); + }); + }); + }, + pollForStories: function(since) { + var _this = this; var actions = 'announcement'; var options = [ - 'now=' + new Date().toISOString(), 'since=' + since.getTime() / 1000, 'include_actions=announcement', 'restriction=open,hifi', @@ -233,81 +297,105 @@ HifiNotifications.prototype = { console.log("Polling for stories"); var url = METAVERSE_SERVER_URL + STORIES_URL + '?' + options.join('&'); console.log(url); - request.get({ - uri: url, - 'auth': { - 'bearer': _token - } - }, function (error, data) { - _this._pollCommon(NotificationType.GOTO, error, data, since); + + _this._pollCommon(NotificationType.STORIES, + url, + since, + function (success, token) { + if(success) { + var options = [ + 'now=' + new Date().toISOString(), + 'include_actions=announcement', + 'restriction=open,hifi', + 'require_online=true', + 'per_page=1' + ]; + var url = METAVERSE_SERVER_URL + STORIES_URL + '?' + options.join('&'); + // call a second time to determine if there are no more stories and we should + // put out the light. + request.get({ + uri: url, + 'auth': { + 'bearer': token + } + }, function(error, data) { + _this._pollToDisableHighlight(NotificationType.GOTO, error, data); + }); + } + }); + }, + pollForConnections: function(since) { + var _this = this; + var _since = since; + IsInterfaceRunning(function(running) { + if(running) { + return; + } var options = [ - 'now=' + new Date().toISOString(), - 'include_actions=announcement', - 'restriction=open,hifi', - 'require_online=true', - 'per_page=1' - ]; - var url = METAVERSE_SERVER_URL + STORIES_URL + '?' + options.join('&'); + 'filter=connections', + 'status=online', + 'page=1', + 'per_page=' + MAX_NOTIFICATION_ITEMS + ]; + console.log("Polling for connections"); + var url = METAVERSE_SERVER_URL + USERS_URL + '?' + options.join('&'); + console.log(url); + var acctInfo = new AccountInfo(); + var token = acctInfo.accessToken(METAVERSE_SERVER_URL); + if(!token) { + return; + } request.get({ uri: url, 'auth': { - 'bearer': _token - } - }, function(error, data) { - _this._pollToDisableHighlight(NotificationType.GOTO, error, data); - }); - }); - }, - pollForConnections: function(since, token) { - var _this = this; - var _since = since; - var options = [ - 'filter=connections', - 'status=online', - 'page=1', - 'per_page=' + MAX_NOTIFICATION_ITEMS - ]; - console.log("Polling for connections"); - var url = METAVERSE_SERVER_URL + USERS_URL + '?' + options.join('&'); - console.log(url); - request.get({ - uri: url, - 'auth': { - 'bearer': token - } - }, function (error, data) { - // Users is a special case as we keep track of online users locally. - var maxNotificationItemCount = since.getTime() ? MAX_NOTIFICATION_ITEMS : STARTUP_MAX_NOTIFICATION_ITEMS; - if (error || !data.body) { - console.log("Error: unable to get " + url); - return false; - } - var content = JSON.parse(data.body); - if(!content || content.status != 'success') { - console.log("Error: unable to get " + url); - return false; - } - console.log(content); - if(!content.total_entries) { - _this.callback(NotificationType.PEOPLE, false); - _this.onlineUsers = new Set([]); - return; - } - - var currentUsers = new Set([]); - content.data.users.forEach(function(user) { - currentUsers.add(user.username); - if(!_this.onlineUsers.has(user.username)) { - _this.callback(NotificationType.PEOPLE, true); - _this.onlineUsers.add(user.username); - var notification = new HifiNotification(NotificationType.PEOPLE, user); - notification.show(); + 'bearer': token } + }, function (error, data) { + // Users is a special case as we keep track of online users locally. + var maxNotificationItemCount = _since.getTime() ? MAX_NOTIFICATION_ITEMS : STARTUP_MAX_NOTIFICATION_ITEMS; + if (error || !data.body) { + console.log("Error: unable to get " + url); + return false; + } + var content = JSON.parse(data.body); + if(!content || content.status != 'success') { + console.log("Error: unable to get " + url); + return false; + } + console.log(content); + if(!content.total_entries) { + _this.menuNotificationCallback(NotificationType.PEOPLE, false); + _this.onlineUsers = new Set([]); + return; + } + + var currentUsers = new Set([]); + var newUsers = new Set([]); + content.data.users.forEach(function(user) { + currentUsers.add(user.username); + if(!_this.onlineUsers.has(user.username)) { + newUsers.add(user); + _this.onlineUsers.add(user.username); + } + }); + _this.onlineUsers = currentUsers; + if(newUsers.size) { + _this.menuNotificationCallback(NotificationType.PEOPLE, true); + } + + if(newUsers.size >= maxNotificationItemCount) { + var notification = new HifiNotification(NotificationType.PEOPLE, newUsers.size); + notification.show(); + return; + } + newUsers.forEach(function(user) { + var notification = new HifiNotification(NotificationType.PEOPLE, user); + notification.show(); + }); }); - _this.onlineUsers = currentUsers; }); }, - pollForEconomicActivity: function(since, token) { + pollForEconomicActivity: function(since) { var _this = this; var options = [ 'since=' + since.getTime() / 1000, @@ -319,16 +407,9 @@ HifiNotifications.prototype = { console.log("Polling for economic activity"); var url = METAVERSE_SERVER_URL + ECONOMIC_ACTIVITY_URL + '?' + options.join('&'); console.log(url); - request.post({ - uri: url, - 'auth': { - 'bearer': token - } - }, function (error, data) { - _this._pollCommon(NotificationType.WALLET, error, data, since); - }); + _this._pollCommon(NotificationType.WALLET, url, since, function () {}); }, - pollForMarketplaceUpdates: function(since, token) { + pollForMarketplaceUpdates: function(since) { var _this = this; var options = [ 'since=' + since.getTime() / 1000, @@ -338,13 +419,21 @@ HifiNotifications.prototype = { console.log("Polling for marketplace update"); var url = METAVERSE_SERVER_URL + UPDATES_URL + '?' + options.join('&'); console.log(url); - request.put({ - uri: url, - 'auth': { - 'bearer': token - } - }, function (error, data) { - _this._pollCommon(NotificationType.MARKETPLACE, error, data, since); + _this._pollCommon(NotificationType.MARKETPLACE, url, since, function (success, token) { + if(success) { + var options = [ + 'page=1', + 'per_page=1' + ]; + request.get({ + uri: url, + 'auth': { + 'bearer': token + } + }, function(error, data) { + _this._pollToDisableHighlight(NotificationType.MARKETPLACE, error, data); + }); + } }); } };