FIX: Ensure first post is loaded before trying to bookmark topic (#9382)

FIX: Ensure first post is loaded before trying to bookmark topic (#9382)

Load first post if not loaded when trying to bookmark topic

  • if the first post was not loaded we could not bookmark it because now we call the toggleBookmarkReminder function on an actual post to open the modal window
  • add a firstPost function to the topic model to get the first post from the stream if it is loaded and if not do a GET request to load it
  • use the firstPost promise when bookmarking topic
diff --git a/app/assets/javascripts/discourse/controllers/topic.js b/app/assets/javascripts/discourse/controllers/topic.js
index c273591..49da4ed 100644
--- a/app/assets/javascripts/discourse/controllers/topic.js
+++ b/app/assets/javascripts/discourse/controllers/topic.js
@@ -453,22 +453,9 @@ export default Controller.extend(bufferedProperty("model"), {
     },
 
     editFirstPost() {
-      const postStream = this.get("model.postStream");
-      let firstPost = postStream.get("posts.firstObject");
-
-      if (firstPost.get("post_number") !== 1) {
-        const postId = postStream.findPostIdForPostNumber(1);
-        // try loading from identity map first
-        firstPost = postStream.findLoadedPost(postId);
-        if (firstPost === undefined) {
-          return this.get("model.postStream")
-            .loadPost(postId)
-            .then(post => {
-              this.send("editPost", post);
-            });
-        }
-      }
-      this.send("editPost", firstPost);
+      this.model
+        .firstPost()
+        .then(firstPost => this.send("editPost", firstPost));
     },
 
     // Post related methods
diff --git a/app/assets/javascripts/discourse/models/topic.js b/app/assets/javascripts/discourse/models/topic.js
index 41734e6..5da7217 100644
--- a/app/assets/javascripts/discourse/models/topic.js
+++ b/app/assets/javascripts/discourse/models/topic.js
@@ -1,4 +1,4 @@
-import EmberObject, { get } from "@ember/object";
+import EmberObject from "@ember/object";
 import { not, notEmpty, equal, and, or } from "@ember/object/computed";
 import { ajax } from "discourse/lib/ajax";
 import { flushMap } from "discourse/models/store";
@@ -407,82 +407,99 @@ const Topic = RestModel.extend({
     }
   },
 
+  firstPost() {
+    const postStream = this.postStream;
+    let firstPost = postStream.get("posts.firstObject");
+
+    if (firstPost.post_number === 1) {
+      return Promise.resolve(firstPost);
+    }
+
+    const postId = postStream.findPostIdForPostNumber(1);
+
+    // try loading from identity map first
+    firstPost = postStream.findLoadedPost(postId);
+    if (firstPost) {
+      return Promise.resolve(firstPost);
+    }
+
+    return this.postStream.loadPost(postId);
+  },
+
   toggleBookmark() {
     if (this.bookmarking) {
       return Promise.resolve();
     }
     this.set("bookmarking", true);
-
-    const stream = this.postStream;
-    const posts = get(stream, "posts");
-    const firstPost =
-      posts && posts[0] && posts[0].get("post_number") === 1 && posts[0];
     const bookmark = !this.bookmarked;
-
-    const toggleBookmarkOnServer = () => {
-      if (bookmark) {
-        if (this.siteSettings.enable_bookmarks_with_reminders) {
-          return firstPost.toggleBookmarkWithReminder().then(() => {
-            this.set("bookmarking", false);
-            return this.afterTopicBookmarked(firstPost);
-          });
+    let posts = this.postStream.posts;
+
+    return this.firstPost().then(firstPost => {
+      const toggleBookmarkOnServer = () => {
+        if (bookmark) {
+          if (this.siteSettings.enable_bookmarks_with_reminders) {
+            return firstPost.toggleBookmarkWithReminder().then(() => {
+              this.set("bookmarking", false);
+              return this.afterTopicBookmarked(firstPost);
+            });
+          } else {
+            return ajax(`/t/${this.id}/bookmark`, { type: "PUT" })
+              .then(() => {
+                this.toggleProperty("bookmarked");
+                return this.afterTopicBookmarked(firstPost);
+              })
+              .catch(popupAjaxError)
+              .finally(() => this.set("bookmarking", false));
+          }
         } else {
-          return ajax(`/t/${this.id}/bookmark`, { type: "PUT" })
+          return ajax(`/t/${this.id}/remove_bookmarks`, { type: "PUT" })
             .then(() => {
               this.toggleProperty("bookmarked");
-              return this.afterTopicBookmarked(firstPost);
+              if (posts) {
+                const updated = [];
+                posts.forEach(post => {
+                  if (post.bookmarked) {
+                    post.set("bookmarked", false);
+                    updated.push(post.id);
+                  }
+                  if (
+                    this.siteSettings.enable_bookmarks_with_reminders &&
+                    post.bookmarked_with_reminder
+                  ) {
+                    post.set("bookmarked_with_reminder", false);
+                    updated.push(post.id);
+                  }
+                });
+                return updated;
+              }
             })
             .catch(popupAjaxError)
             .finally(() => this.set("bookmarking", false));
         }
-      } else {
-        return ajax(`/t/${this.id}/remove_bookmarks`, { type: "PUT" })
-          .then(() => {
-            this.toggleProperty("bookmarked");
-            if (posts) {
-              const updated = [];
-              posts.forEach(post => {
-                if (post.get("bookmarked")) {
-                  post.set("bookmarked", false);
-                  updated.push(post.id);
-                }
-                if (
-                  this.siteSettings.enable_bookmarks_with_reminders &&
-                  post.get("bookmarked_with_reminder")
-                ) {
-                  post.set("bookmarked_with_reminder", false);
-                  updated.push(post.id);
-                }
-              });
-              return updated;
-            }
-          })
-          .catch(popupAjaxError)
-          .finally(() => this.set("bookmarking", false));
-      }
-    };
-
-    const unbookmarkedPosts = [];
-    if (!bookmark && posts) {
-      posts.forEach(
-        post =>
-          (post.get("bookmarked") || post.get("bookmarked_with_reminder")) &&
-          unbookmarkedPosts.push(post)
-      );
-    }
-
-    return new Promise(resolve => {
-      if (unbookmarkedPosts.length > 1) {
-        bootbox.confirm(
-          I18n.t("bookmarks.confirm_clear"),
-          I18n.t("no_value"),
-          I18n.t("yes_value"),
-          confirmed =>
-            confirmed ? toggleBookmarkOnServer().then(resolve) : resolve()
+      };
+
+      const unbookmarkedPosts = [];
+      if (!bookmark && posts) {
+        posts.forEach(
+          post =>
+            (post.bookmarked || post.bookmarked_with_reminder) &&
+            unbookmarkedPosts.push(post)
         );
-      } else {
-        toggleBookmarkOnServer().then(resolve);
       }
+
+      return new Promise(resolve => {
+        if (unbookmarkedPosts.length > 1) {
+          bootbox.confirm(
+            I18n.t("bookmarks.confirm_clear"),
+            I18n.t("no_value"),
+            I18n.t("yes_value"),
+            confirmed =>
+              confirmed ? toggleBookmarkOnServer().then(resolve) : resolve()
+          );
+        } else {
+          toggleBookmarkOnServer().then(resolve);
+        }
+      });
     });
   },
 

GitHub sha: 452d0c86

This commit appears in #9382 which was merged by martin.