mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
Add idle checking, use localStorage for seen notifications
This commit is contained in:
parent
da9913359c
commit
8bbead315d
@ -1,15 +1,18 @@
|
|||||||
|
|
||||||
let primaryTab;
|
let primaryTab;
|
||||||
let liveEnabled;
|
let liveEnabled;
|
||||||
let seenNotificationDates = {};
|
|
||||||
let notificationTagName;
|
let notificationTagName;
|
||||||
let mbClientId;
|
let mbClientId;
|
||||||
|
let lastAction;
|
||||||
|
|
||||||
const focusTrackerKey = "focus-tracker";
|
const focusTrackerKey = "focus-tracker";
|
||||||
|
const seenDataKey = "seen-notifications";
|
||||||
|
const recentUpdateThreshold = 1000 * 60 * 2; // 2 minutes
|
||||||
|
const idleThresholdTime = 1000 * 10; // 10 seconds
|
||||||
|
|
||||||
function init(container) {
|
function init(container) {
|
||||||
liveEnabled = false;
|
liveEnabled = false;
|
||||||
requestPermission().then(function () {
|
requestPermission().then(function() {
|
||||||
try {
|
try {
|
||||||
localStorage.getItem(focusTrackerKey);
|
localStorage.getItem(focusTrackerKey);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -19,10 +22,14 @@ function init(container) {
|
|||||||
}
|
}
|
||||||
liveEnabled = true;
|
liveEnabled = true;
|
||||||
Em.Logger.info('Discourse desktop notifications are enabled.');
|
Em.Logger.info('Discourse desktop notifications are enabled.');
|
||||||
|
}).then(function() {
|
||||||
init2(container);
|
try {
|
||||||
|
init2(container);
|
||||||
}).catch(function () {
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}).catch(function(e) {
|
||||||
|
debugger;
|
||||||
liveEnabled = false;
|
liveEnabled = false;
|
||||||
Em.Logger.info('Discourse desktop notifications are disabled - permission denied.');
|
Em.Logger.info('Discourse desktop notifications are disabled - permission denied.');
|
||||||
});
|
});
|
||||||
@ -30,18 +37,29 @@ function init(container) {
|
|||||||
|
|
||||||
function init2(container) {
|
function init2(container) {
|
||||||
// Load up the current state of the notifications
|
// Load up the current state of the notifications
|
||||||
seenNotificationDates = {};
|
const seenData = JSON.parse(localStorage.getItem(seenDataKey));
|
||||||
Discourse.ajax("/notifications.json?silent=true").then(function(result) {
|
let markAllSeen = true;
|
||||||
updateSeenNotificationDatesFrom(result);
|
if (seenData) {
|
||||||
});
|
const lastUpdatedAt = new Date(seenData.updated_at);
|
||||||
|
if (lastUpdatedAt.getTime() + recentUpdateThreshold > new Date().getTime()) {
|
||||||
|
// The following conditions are met:
|
||||||
|
// - This is a new Discourse tab
|
||||||
|
// - The seen notification data was updated in the last 2 minutes
|
||||||
|
// Therefore, there is no need to reset the data.
|
||||||
|
markAllSeen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (markAllSeen) {
|
||||||
|
Discourse.ajax("/notifications.json?silent=true").then(function(result) {
|
||||||
|
updateSeenNotificationDatesFrom(result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
notificationTagName = "discourse-notification-popup-" + Discourse.SiteSettings.title;
|
notificationTagName = "discourse-notification-popup-" + Discourse.SiteSettings.title;
|
||||||
|
|
||||||
const messageBus = container.lookup('message-bus:main');
|
const messageBus = container.lookup('message-bus:main');
|
||||||
mbClientId = messageBus.clientId;
|
mbClientId = messageBus.clientId;
|
||||||
|
|
||||||
console.info("My client ID is", mbClientId);
|
|
||||||
|
|
||||||
window.addEventListener("storage", function(e) {
|
window.addEventListener("storage", function(e) {
|
||||||
// note: This event only fires when other tabs setItem()
|
// note: This event only fires when other tabs setItem()
|
||||||
const key = e.key;
|
const key = e.key;
|
||||||
@ -50,12 +68,10 @@ function init2(container) {
|
|||||||
}
|
}
|
||||||
if (primaryTab) {
|
if (primaryTab) {
|
||||||
primaryTab = false;
|
primaryTab = false;
|
||||||
console.debug("Releasing focus to", e.oldValue);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
window.addEventListener("focus", function() {
|
window.addEventListener("focus", function() {
|
||||||
if (!primaryTab) {
|
if (!primaryTab) {
|
||||||
console.debug("Grabbing focus from", localStorage.getItem(focusTrackerKey));
|
|
||||||
primaryTab = true;
|
primaryTab = true;
|
||||||
localStorage.setItem(focusTrackerKey, mbClientId);
|
localStorage.setItem(focusTrackerKey, mbClientId);
|
||||||
}
|
}
|
||||||
@ -66,8 +82,18 @@ function init2(container) {
|
|||||||
} else {
|
} else {
|
||||||
primaryTab = true;
|
primaryTab = true;
|
||||||
localStorage.setItem(focusTrackerKey, mbClientId);
|
localStorage.setItem(focusTrackerKey, mbClientId);
|
||||||
console.debug("Grabbing focus");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.addEventListener("scroll", resetIdle);
|
||||||
|
window.addEventListener("mouseover", resetIdle);
|
||||||
|
Discourse.PageTracker.on("change", resetIdle);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetIdle() {
|
||||||
|
lastAction = Date.now();
|
||||||
|
}
|
||||||
|
function isIdle() {
|
||||||
|
return lastAction + idleThresholdTime < Date.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call-in point from message bus
|
// Call-in point from message bus
|
||||||
@ -86,10 +112,15 @@ function onNotification(currentUser) {
|
|||||||
const unreadCount = unread.length;
|
const unreadCount = unread.length;
|
||||||
const unseenCount = unseen.length;
|
const unseenCount = unseen.length;
|
||||||
|
|
||||||
|
|
||||||
|
// If all notifications are seen, don't display
|
||||||
if (unreadCount === 0 || unseenCount === 0) {
|
if (unreadCount === 0 || unseenCount === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// If active in last 10 seconds, don't display
|
||||||
|
if (!isIdle()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let bodyParts = [];
|
let bodyParts = [];
|
||||||
|
|
||||||
@ -132,8 +163,32 @@ function onNotification(currentUser) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility function
|
const DATA_VERSION = 2;
|
||||||
// Wraps Notification.requestPermission in a Promise
|
function updateSeenNotificationDatesFrom(notifications) {
|
||||||
|
const oldSeenData = JSON.parse(localStorage.getItem(seenDataKey));
|
||||||
|
const oldSeenNotificationDates = (oldSeenData && oldSeenData.v === DATA_VERSION) ? oldSeenData.data : [];
|
||||||
|
let newSeenNotificationDates = [];
|
||||||
|
let previouslyUnseenNotifications = [];
|
||||||
|
|
||||||
|
notifications.forEach(function(notification) {
|
||||||
|
const dateString = new Date(notification.created_at).toUTCString();
|
||||||
|
|
||||||
|
if (oldSeenNotificationDates.indexOf(dateString) === -1) {
|
||||||
|
previouslyUnseenNotifications.push(notification);
|
||||||
|
}
|
||||||
|
newSeenNotificationDates.push(dateString);
|
||||||
|
});
|
||||||
|
|
||||||
|
localStorage.setItem(seenDataKey, JSON.stringify({
|
||||||
|
data: newSeenNotificationDates,
|
||||||
|
updated_at: new Date(),
|
||||||
|
v: DATA_VERSION
|
||||||
|
}));
|
||||||
|
return previouslyUnseenNotifications;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility function
|
||||||
|
// Wraps Notification.requestPermission in a Promise
|
||||||
function requestPermission() {
|
function requestPermission() {
|
||||||
return new Ember.RSVP.Promise(function(resolve, reject) {
|
return new Ember.RSVP.Promise(function(resolve, reject) {
|
||||||
Notification.requestPermission(function(status) {
|
Notification.requestPermission(function(status) {
|
||||||
@ -155,25 +210,6 @@ function i18nKey(notification) {
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility function
|
|
||||||
function updateSeenNotificationDatesFrom(notifications) {
|
|
||||||
const oldSeenNotificationDates = seenNotificationDates;
|
|
||||||
let newSeenNotificationDates = {};
|
|
||||||
let previouslyUnseenNotifications = [];
|
|
||||||
|
|
||||||
notifications.forEach(function(notification) {
|
|
||||||
const dateString = new Date(notification.created_at).toUTCString();
|
|
||||||
|
|
||||||
if (!oldSeenNotificationDates[dateString]) {
|
|
||||||
previouslyUnseenNotifications.push(notification);
|
|
||||||
}
|
|
||||||
newSeenNotificationDates[dateString] = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
seenNotificationDates = newSeenNotificationDates;
|
|
||||||
return previouslyUnseenNotifications;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exported for controllers/notification.js.es6
|
// Exported for controllers/notification.js.es6
|
||||||
function notificationUrl(it) {
|
function notificationUrl(it) {
|
||||||
var badgeId = it.get("data.badge_id");
|
var badgeId = it.get("data.badge_id");
|
||||||
|
Loading…
Reference in New Issue
Block a user