diff --git a/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js b/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js index 498c920e9d6..b04f4bba278 100644 --- a/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js +++ b/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js @@ -83,6 +83,11 @@ const DEFAULT_BINDINGS = { const animationDuration = 100; +function preventKeyboardEvent(event) { + event.preventDefault(); + event.stopPropagation(); +} + export default { init(keyTrapper, container) { this.keyTrapper = keyTrapper; @@ -175,20 +180,39 @@ export default { }, toggleBookmark(event) { - event.preventDefault(); - event.stopPropagation(); + const selectedPost = this._getSelectedPost(); + if (selectedPost) { + preventKeyboardEvent(event); + this.sendToSelectedPost("toggleBookmark", selectedPost); + return; + } - this.sendToSelectedPost("toggleBookmark"); - this.sendToTopicListItemView("toggleBookmark"); + const selectedTopicListItem = this._getSelectedTopicListItem(); + if (selectedTopicListItem) { + preventKeyboardEvent(event); + this.sendToTopicListItemView("toggleBookmark", selectedTopicListItem); + return; + } + + this._bookmarkCurrentTopic(event); }, - toggleBookmarkTopic() { + toggleBookmarkTopic(event) { + const selectedTopicListItem = this._getSelectedTopicListItem(); + if (selectedTopicListItem) { + preventKeyboardEvent(event); + this.sendToTopicListItemView("toggleBookmark", selectedTopicListItem); + return; + } + + this._bookmarkCurrentTopic(event); + }, + + _bookmarkCurrentTopic(event) { const topic = this.currentTopic(); - // BIG hack, need a cleaner way - if (topic && $(".posts-wrapper").length > 0) { + if (topic && document.querySelectorAll(".posts-wrapper").length) { + preventKeyboardEvent(event); this.container.lookup("controller:topic").send("toggleBookmark"); - } else { - this.sendToTopicListItemView("toggleBookmark"); } }, @@ -380,8 +404,8 @@ export default { }); }, - sendToTopicListItemView(action) { - const elem = $("tr.selected.topic-list-item.ember-view")[0]; + sendToTopicListItemView(action, elem) { + elem = elem || document.querySelector("tr.selected.topic-list-item"); if (elem) { const registry = this.container.lookup("-view-registry:main"); if (registry) { @@ -401,15 +425,18 @@ export default { } }, - sendToSelectedPost(action) { - const container = this.container; + sendToSelectedPost(action, elem) { // TODO: We should keep track of the post without a CSS class - let selectedPostId = parseInt( - $(".topic-post.selected article.boxed").data("post-id"), - 10 - ); + const selectedPost = + elem || document.querySelector(".topic-post.selected article.boxed"); + + let selectedPostId; + if (selectedPost) { + selectedPostId = parseInt(selectedPost.dataset.postId, 10); + } + if (selectedPostId) { - const topicController = container.lookup("controller:topic"); + const topicController = this.container.lookup("controller:topic"); const post = topicController .get("model.postStream.posts") .findBy("id", selectedPostId); @@ -418,7 +445,7 @@ export default { let actionMethod = topicController.actions[action]; if (!actionMethod) { - const topicRoute = container.lookup("route:topic"); + const topicRoute = this.container.lookup("route:topic"); actionMethod = topicRoute.actions[action]; } @@ -696,6 +723,14 @@ export default { this.container.lookup("controller:topic").send("replyToPost"); }, + _getSelectedPost() { + return document.querySelector(".topic-post.selected article[data-post-id]"); + }, + + _getSelectedTopicListItem() { + return document.querySelector("tr.selected.topic-list-item"); + }, + deferTopic() { this.container.lookup("controller:topic").send("deferTopic"); }, diff --git a/app/assets/javascripts/discourse/app/models/topic.js b/app/assets/javascripts/discourse/app/models/topic.js index 1cbab38942f..46be3e7feeb 100644 --- a/app/assets/javascripts/discourse/app/models/topic.js +++ b/app/assets/javascripts/discourse/app/models/topic.js @@ -410,19 +410,22 @@ const Topic = RestModel.extend({ const postStream = this.postStream; let firstPost = postStream.get("posts.firstObject"); - if (firstPost.post_number === 1) { + if (firstPost && firstPost.post_number === 1) { return Promise.resolve(firstPost); } const postId = postStream.findPostIdForPostNumber(1); + if (postId) { + // try loading from identity map first + firstPost = postStream.findLoadedPost(postId); + if (firstPost) { + return Promise.resolve(firstPost); + } - // try loading from identity map first - firstPost = postStream.findLoadedPost(postId); - if (firstPost) { - return Promise.resolve(firstPost); + return this.postStream.loadPost(postId); + } else { + return this.postStream.loadPostByPostNumber(1); } - - return this.postStream.loadPost(postId); }, toggleBookmark() {