FEATURE: add support for defer topic functionality

FEATURE: add support for defer topic functionality

This feature allows end users to “defer” topics by marking them unread

The functionality is default disabled. This also introduces the new site setting default_other_enable_defer: to enable this by default on new user accounts.

diff --git a/app/assets/javascripts/discourse/components/topic-footer-buttons.js.es6 b/app/assets/javascripts/discourse/components/topic-footer-buttons.js.es6
index 0087226..0c487e7 100644
--- a/app/assets/javascripts/discourse/components/topic-footer-buttons.js.es6
+++ b/app/assets/javascripts/discourse/components/topic-footer-buttons.js.es6
@@ -32,6 +32,8 @@ export default Ember.Component.extend({
 
   canInviteTo: Ember.computed.alias("topic.details.can_invite_to"),
 
+  canDefer: Ember.computed.alias("currentUser.enable_defer"),
+
   inviteDisabled: Ember.computed.or(
     "topic.archived",
     "topic.closed",
diff --git a/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6
index 915db2d..072c42c 100644
--- a/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6
+++ b/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6
@@ -31,6 +31,7 @@ export default Ember.Controller.extend(PreferencesTabController, {
       "external_links_in_new_tab",
       "dynamic_favicon",
       "enable_quoting",
+      "enable_defer",
       "automatically_unpin_topics",
       "allow_private_messages",
       "homepage_id",
diff --git a/app/assets/javascripts/discourse/controllers/topic.js.es6 b/app/assets/javascripts/discourse/controllers/topic.js.es6
index 1ec3b6c..1579696 100644
--- a/app/assets/javascripts/discourse/controllers/topic.js.es6
+++ b/app/assets/javascripts/discourse/controllers/topic.js.es6
@@ -405,6 +405,27 @@ export default Ember.Controller.extend(bufferedProperty("model"), {
       }
     },
 
+    deferTopic() {
+      const screenTrack = Discourse.__container__.lookup("screen-track:main");
+      const currentUser = this.currentUser;
+      const topic = this.model;
+
+      screenTrack.reset();
+      screenTrack.stop();
+      const goToPath = topic.get("isPrivateMessage")
+        ? currentUser.pmPath(topic)
+        : "/";
+      ajax("/t/" + topic.get("id") + "/timings.json?last=1", { type: "DELETE" })
+        .then(() => {
+          const highestSeenByTopic = Discourse.Session.currentProp(
+            "highestSeenByTopic"
+          );
+          highestSeenByTopic[topic.get("id")] = null;
+          DiscourseURL.routeTo(goToPath);
+        })
+        .catch(popupAjaxError);
+    },
+
     editFirstPost() {
       const postStream = this.get("model.postStream");
       let firstPost = postStream.get("posts.firstObject");
diff --git a/app/assets/javascripts/discourse/initializers/topic-footer-buttons.js.es6 b/app/assets/javascripts/discourse/initializers/topic-footer-buttons.js.es6
index ccb2e2e..fce251f 100644
--- a/app/assets/javascripts/discourse/initializers/topic-footer-buttons.js.es6
+++ b/app/assets/javascripts/discourse/initializers/topic-footer-buttons.js.es6
@@ -148,5 +148,20 @@ export default {
         return this.showEditOnFooter;
       }
     });
+
+    registerTopicFooterButton({
+      id: "defer",
+      icon: "circle",
+      priority: 300,
+      label: "topic.defer.title",
+      title: "topic.defer.help",
+      action: "deferTopic",
+      displayed() {
+        return this.canDefer;
+      },
+      dropdown() {
+        return this.site.mobileView;
+      }
+    });
   }
 };
diff --git a/app/assets/javascripts/discourse/models/user.js.es6 b/app/assets/javascripts/discourse/models/user.js.es6
index 90b47dc..b9064d1 100644
--- a/app/assets/javascripts/discourse/models/user.js.es6
+++ b/app/assets/javascripts/discourse/models/user.js.es6
@@ -271,6 +271,7 @@ const User = RestModel.extend({
       "email_previous_replies",
       "dynamic_favicon",
       "enable_quoting",
+      "enable_defer",
       "automatically_unpin_topics",
       "digest_after_minutes",
       "new_topic_duration_minutes",
@@ -338,6 +339,7 @@ const User = RestModel.extend({
         const userProps = Ember.getProperties(
           this.user_option,
           "enable_quoting",
+          "enable_defer",
           "external_links_in_new_tab",
           "dynamic_favicon"
         );
diff --git a/app/assets/javascripts/discourse/templates/preferences/interface.hbs b/app/assets/javascripts/discourse/templates/preferences/interface.hbs
index e1192d1..854c511 100644
--- a/app/assets/javascripts/discourse/templates/preferences/interface.hbs
+++ b/app/assets/javascripts/discourse/templates/preferences/interface.hbs
@@ -49,6 +49,7 @@
 
   {{preference-checkbox labelKey="user.external_links_in_new_tab" checked=model.user_option.external_links_in_new_tab}}
   {{preference-checkbox labelKey="user.enable_quoting" checked=model.user_option.enable_quoting}}
+  {{preference-checkbox labelKey="user.enable_defer" checked=model.user_option.enable_defer}}
   {{#if siteSettings.automatically_unpin_topics}}
     {{preference-checkbox labelKey="user.automatically_unpin_topics" checked=model.user_option.automatically_unpin_topics}}
   {{/if}}
diff --git a/app/assets/javascripts/discourse/templates/topic.hbs b/app/assets/javascripts/discourse/templates/topic.hbs
index b47f793..f58cc7f 100644
--- a/app/assets/javascripts/discourse/templates/topic.hbs
+++ b/app/assets/javascripts/discourse/templates/topic.hbs
@@ -301,6 +301,7 @@
                     showFlagTopic=(route-action "showFlagTopic")
                     toggleArchiveMessage=(action "toggleArchiveMessage")
                     editFirstPost=(action "editFirstPost")
+                    deferTopic=(action "deferTopic")
                     replyToPost=(action "replyToPost")}}
                 {{else}}
                   <div id="topic-footer-buttons">
diff --git a/app/models/user_option.rb b/app/models/user_option.rb
index 7cf837e..a5e583f 100644
--- a/app/models/user_option.rb
+++ b/app/models/user_option.rb
@@ -53,6 +53,7 @@ class UserOption < ActiveRecord::Base
     self.email_in_reply_to = SiteSetting.default_email_in_reply_to
 
     self.enable_quoting = SiteSetting.default_other_enable_quoting
+    self.enable_defer = SiteSetting.default_other_enable_defer
     self.external_links_in_new_tab = SiteSetting.default_other_external_links_in_new_tab
     self.dynamic_favicon = SiteSetting.default_other_dynamic_favicon
 
@@ -222,6 +223,7 @@ end
 #  email_level                      :integer          default(1), not null
 #  email_messages_level             :integer          default(0), not null
 #  title_count_mode_key             :integer          default(0), not null
+#  enable_defer                     :boolean          default(FALSE), not null
 #
 # Indexes
 #
diff --git a/app/serializers/current_user_serializer.rb b/app/serializers/current_user_serializer.rb
index ad2501a..8cfb348 100644
--- a/app/serializers/current_user_serializer.rb
+++ b/app/serializers/current_user_serializer.rb
@@ -16,6 +16,7 @@ class CurrentUserSerializer < BasicUserSerializer
              :reply_count,
              :topic_count,
              :enable_quoting,
+             :enable_defer,
              :external_links_in_new_tab,
              :dynamic_favicon,
              :trust_level,
@@ -79,6 +80,10 @@ class CurrentUserSerializer < BasicUserSerializer
     object.user_option.enable_quoting
   end
 
+  def enable_defer
+    object.user_option.enable_defer
+  end
+
   def external_links_in_new_tab
     object.user_option.external_links_in_new_tab
   end
diff --git a/app/serializers/user_option_serializer.rb b/app/serializers/user_option_serializer.rb
index 646ae4a..4a8a5a1 100644
--- a/app/serializers/user_option_serializer.rb
+++ b/app/serializers/user_option_serializer.rb
@@ -10,6 +10,7 @@ class UserOptionSerializer < ApplicationSerializer
              :external_links_in_new_tab,
              :dynamic_favicon,
              :enable_quoting,
+             :enable_defer,
              :digest_after_minutes,
              :automatically_unpin_topics,
              :auto_track_topics_after_msecs,
diff --git a/app/services/user_updater.rb b/app/services/user_updater.rb
index 38983b3..ac1e489 100644
--- a/app/services/user_updater.rb

[... diff too long, it was truncated ...]

GitHub sha: 3b8819f0

1 Like

This commit has been mentioned on Discourse Meta. There might be relevant details there:

This commit has been mentioned on Discourse Meta. There might be relevant details there: