diff --git a/app/assets/javascripts/discourse/app/controllers/topic.js b/app/assets/javascripts/discourse/app/controllers/topic.js index 9a2eb3804c5..6ff0dfe9beb 100644 --- a/app/assets/javascripts/discourse/app/controllers/topic.js +++ b/app/assets/javascripts/discourse/app/controllers/topic.js @@ -19,10 +19,8 @@ import bootbox from "bootbox"; import { bufferedProperty } from "discourse/mixins/buffered-content"; import { buildQuote } from "discourse/lib/quote"; import { deepMerge } from "discourse-common/lib/object"; -import discourseDebounce from "discourse-common/lib/debounce"; import { escapeExpression } from "discourse/lib/utilities"; import { extractLinkMeta } from "discourse/lib/render-topic-featured-link"; -import isElementInViewport from "discourse/lib/is-element-in-viewport"; import { popupAjaxError } from "discourse/lib/ajax-error"; import { inject as service } from "@ember/service"; import showModal from "discourse/lib/show-modal"; @@ -1679,52 +1677,11 @@ export default Controller.extend(bufferedProperty("model"), { } } } - - // scroll to bottom is very specific to new posts from discobot - // hence the -2 check (discobot id). We can shift all this code - // to discobot plugin longer term - if ( - topic.get("isPrivateMessage") && - this.currentUser && - this.currentUser.get("id") !== data.user_id && - data.user_id === -2 && - data.type === "created" - ) { - const postNumber = data.post_number; - const notInPostStream = - topic.get("highest_post_number") <= postNumber; - const postNumberDifference = postNumber - topic.get("currentPost"); - - if ( - notInPostStream && - postNumberDifference > 0 && - postNumberDifference < 7 - ) { - this._scrollToPost(data.post_number); - } - } }, this.get("model.message_bus_last_id") ); }, - _scrollToPost(postNumber) { - discourseDebounce( - this, - function () { - const $post = $(`.topic-post article#post_${postNumber}`); - - if ($post.length === 0 || isElementInViewport($post[0])) { - return; - } - - $("html, body").animate({ scrollTop: $post.offset().top }, 1000); - }, - postNumber, - 500 - ); - }, - unsubscribe() { // never unsubscribe when navigating from topic to topic if (!this.get("model.id")) { diff --git a/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js b/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js index bf572e0eaab..42e3a0ad1f3 100644 --- a/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js +++ b/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js @@ -708,10 +708,11 @@ export default { } }, - _scrollTo(scrollTop, complete) { - $("html, body") - .stop(true, true) - .animate({ scrollTop }, { duration: animationDuration, complete }); + _scrollTo(scrollTop) { + window.scrollTo({ + top: scrollTop, + behavior: "smooth", + }); }, _scrollList($article) { @@ -738,13 +739,7 @@ export default { scrollPos = 0; } - if (this._scrollAnimation) { - this._scrollAnimation.stop(); - } - this._scrollAnimation = $("html, body").animate( - { scrollTop: scrollPos + "px" }, - animationDuration - ); + this._scrollTo(scrollPos); }, categoriesTopicsList() { diff --git a/plugins/discourse-narrative-bot/assets/javascripts/initializers/new-user-narrative.js b/plugins/discourse-narrative-bot/assets/javascripts/initializers/new-user-narrative.js index 5e1830e6f6b..7072e9d4b96 100644 --- a/plugins/discourse-narrative-bot/assets/javascripts/initializers/new-user-narrative.js +++ b/plugins/discourse-narrative-bot/assets/javascripts/initializers/new-user-narrative.js @@ -1,4 +1,6 @@ import { ajax } from "discourse/lib/ajax"; +import discourseDebounce from "discourse-common/lib/debounce"; +import isElementInViewport from "discourse/lib/is-element-in-viewport"; import { withPluginApi } from "discourse/lib/plugin-api"; const PLUGIN_ID = "new-user-narrative"; @@ -39,6 +41,68 @@ function initialize(api) { } return this._super(bookmark, post); }, + + subscribe() { + this._super(...arguments); + + this.messageBus.subscribe(`/topic/${this.get("model.id")}`, (data) => { + const topic = this.model; + + // scroll only for discobot (-2 is discobot id) + if ( + topic.get("isPrivateMessage") && + this.currentUser && + this.currentUser.get("id") !== data.user_id && + data.user_id === -2 && + data.type === "created" + ) { + const postNumber = data.post_number; + const notInPostStream = + topic.get("highest_post_number") <= postNumber; + const postNumberDifference = postNumber - topic.get("currentPost"); + + if ( + notInPostStream && + postNumberDifference > 0 && + postNumberDifference < 7 + ) { + this._scrollToDiscobotPost(data.post_number); + } + } + }); + // No need to unsubscribe, core unsubscribes /topic/* routes + }, + + _scrollToDiscobotPost(postNumber) { + discourseDebounce( + this, + function () { + const post = document.querySelector( + `.topic-post article#post_${postNumber}` + ); + + if (!post || isElementInViewport(post)) { + return; + } + + const headerOffset = + parseInt( + getComputedStyle(document.body).getPropertyValue( + "--header-offset" + ), + 10 + ) || 0; + const viewportOffset = post.getBoundingClientRect(); + + window.scrollTo({ + top: window.scrollY + viewportOffset.top - headerOffset, + behavior: "smooth", + }); + }, + postNumber, + 500 + ); + }, }); api.attachWidgetAction("header", "headerSearchContextTrigger", function () {