diff --git a/app/assets/javascripts/discourse.js.es6 b/app/assets/javascripts/discourse.js.es6 index 41eba5d39b9..6e24d1e3d1d 100644 --- a/app/assets/javascripts/discourse.js.es6 +++ b/app/assets/javascripts/discourse.js.es6 @@ -41,7 +41,7 @@ const Discourse = Ember.Application.extend({ Resolver: buildResolver("discourse"), - @observes("_docTitle", "hasFocus", "notifyCount") + @observes("_docTitle", "hasFocus", "contextCount", "notificationCount") _titleChanged() { let title = this.get("_docTitle") || Discourse.SiteSettings.title; @@ -51,15 +51,18 @@ const Discourse = Ember.Application.extend({ $("title").text(title); } - const notifyCount = this.get("notifyCount"); - if (notifyCount > 0 && !Discourse.User.currentProp("dynamic_favicon")) { - title = `(${notifyCount}) ${title}`; + var displayCount = Discourse.User.current() + ? this.get("notificationCount") + : this.get("contextCount"); + + if (displayCount > 0 && !Discourse.User.currentProp("dynamic_favicon")) { + title = `(${displayCount}) ${title}`; } document.title = title; }, - @observes("notifyCount") + @observes("contextCount", "notificationCount") faviconChanged() { if (Discourse.User.currentProp("dynamic_favicon")) { let url = Discourse.SiteSettings.site_favicon_url; @@ -71,7 +74,11 @@ const Discourse = Ember.Application.extend({ url = Discourse.getURL("/favicon/proxied?" + encodeURIComponent(url)); } - new window.Favcount(url).set(this.get("notifyCount")); + var displayCount = Discourse.User.current() + ? this.get("notificationCount") + : this.get("contextCount"); + + new window.Favcount(url).set(displayCount); } }, @@ -83,23 +90,33 @@ const Discourse = Ember.Application.extend({ }); }, - notifyTitle(count) { - this.set("notifyCount", count); + updateContextCount(count) { + this.set("contextCount", count); }, - notifyBackgroundCountIncrement() { + updateNotificationCount(count) { + if (!this.get("hasFocus")) { + this.set("notificationCount", count); + } + }, + + incrementBackgroundContextCount() { if (!this.get("hasFocus")) { this.set("backgroundNotify", true); - this.set("notifyCount", (this.get("notifyCount") || 0) + 1); + this.set("contextCount", (this.get("contextCount") || 0) + 1); } }, @observes("hasFocus") - resetBackgroundNotifyCount() { + resetCounts() { if (this.get("hasFocus") && this.get("backgroundNotify")) { - this.set("notifyCount", 0); + this.set("contextCount", 0); } this.set("backgroundNotify", false); + + if (this.get("hasFocus")) { + this.set("notificationCount", 0); + } }, authenticationComplete(options) { diff --git a/app/assets/javascripts/discourse/components/discovery-topics-list.js.es6 b/app/assets/javascripts/discourse/components/discovery-topics-list.js.es6 index 465a8d10a08..fdc448f3eef 100644 --- a/app/assets/javascripts/discourse/components/discovery-topics-list.js.es6 +++ b/app/assets/javascripts/discourse/components/discovery-topics-list.js.es6 @@ -24,7 +24,7 @@ const DiscoveryTopicsListComponent = Ember.Component.extend( @observes("incomingCount") _updateTitle() { - Discourse.notifyTitle(this.get("incomingCount")); + Discourse.updateContextCount(this.get("incomingCount")); }, saveScrollPosition() { @@ -38,7 +38,7 @@ const DiscoveryTopicsListComponent = Ember.Component.extend( actions: { loadMore() { - Discourse.notifyTitle(0); + Discourse.updateContextCount(0); this.get("model") .loadMore() .then(hasMoreResults => { diff --git a/app/assets/javascripts/discourse/controllers/topic.js.es6 b/app/assets/javascripts/discourse/controllers/topic.js.es6 index c8ae6d66fcf..a51c2dda9a6 100644 --- a/app/assets/javascripts/discourse/controllers/topic.js.es6 +++ b/app/assets/javascripts/discourse/controllers/topic.js.es6 @@ -1226,7 +1226,7 @@ export default Ember.Controller.extend(bufferedProperty("model"), { case "created": { postStream.triggerNewPostInStream(data.id).then(() => refresh()); if (this.get("currentUser.id") !== data.user_id) { - Discourse.notifyBackgroundCountIncrement(); + Discourse.incrementBackgroundContextCount(); } break; } diff --git a/app/assets/javascripts/discourse/initializers/title-notifications.js.es6 b/app/assets/javascripts/discourse/initializers/title-notifications.js.es6 new file mode 100644 index 00000000000..d84cfc1cc4b --- /dev/null +++ b/app/assets/javascripts/discourse/initializers/title-notifications.js.es6 @@ -0,0 +1,18 @@ +export default { + name: "title-notifications", + after: "message-bus", + + initialize(container) { + const appEvents = container.lookup("app-events:main"); + const user = container.lookup("current-user:main"); + + if (!user) return; // must be logged in + + appEvents.on("notifications:changed", () => { + let notifications = + user.get("unread_notifications") + user.get("unread_private_messages"); + + Discourse.updateNotificationCount(notifications); + }); + } +}; diff --git a/app/assets/javascripts/discourse/lib/clean-dom.js.es6 b/app/assets/javascripts/discourse/lib/clean-dom.js.es6 index c848ace5553..59157189f63 100644 --- a/app/assets/javascripts/discourse/lib/clean-dom.js.es6 +++ b/app/assets/javascripts/discourse/lib/clean-dom.js.es6 @@ -22,7 +22,7 @@ function _clean() { .not(".no-blur") .blur(); - Discourse.set("notifyCount", 0); + Discourse.set("contextCount", 0); Discourse.__container__.lookup("route:application").send("closeModal"); const hideDropDownFunction = $("html").data("hide-dropdown"); if (hideDropDownFunction) { diff --git a/test/javascripts/lib/discourse-test.js.es6 b/test/javascripts/lib/discourse-test.js.es6 index 94498a16462..014ec78c717 100644 --- a/test/javascripts/lib/discourse-test.js.es6 +++ b/test/javascripts/lib/discourse-test.js.es6 @@ -1,3 +1,5 @@ +import { logIn, replaceCurrentUser } from "helpers/qunit-helpers"; + QUnit.module("lib:discourse"); QUnit.test("getURL on subfolder install", assert => { @@ -24,3 +26,64 @@ QUnit.test("getURLWithCDN on subfolder install with S3", assert => { Discourse.S3CDN = null; Discourse.S3BaseUrl = null; }); + +QUnit.test("title counts are updated correctly", assert => { + Discourse.set("hasFocus", true); + Discourse.set("contextCount", 0); + Discourse.set("notificationCount", 0); + + Discourse.set("_docTitle", "Test Title"); + + assert.equal(document.title, "Test Title", "title is correct"); + + Discourse.updateNotificationCount(5); + assert.equal(document.title, "Test Title", "title doesn't change with focus"); + + Discourse.incrementBackgroundContextCount(); + assert.equal(document.title, "Test Title", "title doesn't change with focus"); + + Discourse.set("hasFocus", false); + + Discourse.updateNotificationCount(5); + assert.equal( + document.title, + "Test Title", + "notification count ignored for anon" + ); + + Discourse.incrementBackgroundContextCount(); + assert.equal( + document.title, + "(1) Test Title", + "title changes when incremented for anon" + ); + + logIn(); + replaceCurrentUser({ dynamic_favicon: false }); + + Discourse.set("hasFocus", true); + Discourse.set("hasFocus", false); + + Discourse.incrementBackgroundContextCount(); + assert.equal( + document.title, + "Test Title", + "title doesn't change when incremented for logged in" + ); + + Discourse.updateNotificationCount(3); + assert.equal( + document.title, + "(3) Test Title", + "title includes notification count for logged in user" + ); + + Discourse.set("hasFocus", false); + Discourse.set("hasFocus", true); + + assert.equal( + document.title, + "Test Title", + "counter dissappears after focus, and doesn't reappear until another notification arrives" + ); +});