FIX: Only use lastViewedTopic when going 'back' to a topic list (#22594)
Using the lastViewedTopicId indiscriminately can cause strange scrolling behavior when navigating to a **different** topic list after viewing a topic. We only want to refocus the topic when going 'back' to the same topic list which originally triggered the navigation.
This commit is contained in:
parent
9c915345ea
commit
30c152c5a7
|
@ -13,6 +13,7 @@ import { schedule } from "@ember/runloop";
|
||||||
import { topicTitleDecorators } from "discourse/components/topic-title";
|
import { topicTitleDecorators } from "discourse/components/topic-title";
|
||||||
import { wantsNewWindow } from "discourse/lib/intercept-click";
|
import { wantsNewWindow } from "discourse/lib/intercept-click";
|
||||||
import { htmlSafe } from "@ember/template";
|
import { htmlSafe } from "@ember/template";
|
||||||
|
import { inject as service } from "@ember/service";
|
||||||
|
|
||||||
export function showEntrance(e) {
|
export function showEntrance(e) {
|
||||||
let target = $(e.target);
|
let target = $(e.target);
|
||||||
|
@ -39,11 +40,18 @@ export function navigateToTopic(topic, href) {
|
||||||
// so skip setting it early.
|
// so skip setting it early.
|
||||||
this.appEvents.trigger("header:update-topic", topic);
|
this.appEvents.trigger("header:update-topic", topic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.session.set("lastTopicIdViewed", {
|
||||||
|
topicId: topic.id,
|
||||||
|
historyUuid: this.router.location.getState?.().uuid,
|
||||||
|
});
|
||||||
|
|
||||||
DiscourseURL.routeTo(href || topic.get("url"));
|
DiscourseURL.routeTo(href || topic.get("url"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
|
router: service(),
|
||||||
tagName: "tr",
|
tagName: "tr",
|
||||||
classNameBindings: [":topic-list-item", "unboundClassNames", "topic.visited"],
|
classNameBindings: [":topic-list-item", "unboundClassNames", "topic.visited"],
|
||||||
attributeBindings: ["data-topic-id", "role", "ariaLevel:aria-level"],
|
attributeBindings: ["data-topic-id", "role", "ariaLevel:aria-level"],
|
||||||
|
@ -328,7 +336,14 @@ export default Component.extend({
|
||||||
|
|
||||||
_highlightIfNeeded: on("didInsertElement", function () {
|
_highlightIfNeeded: on("didInsertElement", function () {
|
||||||
// highlight the last topic viewed
|
// highlight the last topic viewed
|
||||||
if (this.session.get("lastTopicIdViewed") === this.get("topic.id")) {
|
const lastViewedTopicInfo = this.session.get("lastTopicIdViewed");
|
||||||
|
|
||||||
|
const isLastViewedTopic =
|
||||||
|
lastViewedTopicInfo?.topicId === this.topic.id &&
|
||||||
|
lastViewedTopicInfo?.historyUuid ===
|
||||||
|
this.router.location.getState?.().uuid;
|
||||||
|
|
||||||
|
if (isLastViewedTopic) {
|
||||||
this.session.set("lastTopicIdViewed", null);
|
this.session.set("lastTopicIdViewed", null);
|
||||||
this.highlight({ isLastViewedTopic: true });
|
this.highlight({ isLastViewedTopic: true });
|
||||||
} else if (this.get("topic.highlight")) {
|
} else if (this.get("topic.highlight")) {
|
||||||
|
|
|
@ -323,9 +323,6 @@ const TopicRoute = DiscourseRoute.extend({
|
||||||
activate() {
|
activate() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
this.set("isTransitioning", false);
|
this.set("isTransitioning", false);
|
||||||
|
|
||||||
const topic = this.modelFor("topic");
|
|
||||||
this.session.set("lastTopicIdViewed", parseInt(topic.get("id"), 10));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
deactivate() {
|
deactivate() {
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
import { acceptance, query } from "discourse/tests/helpers/qunit-helpers";
|
|
||||||
import { test } from "qunit";
|
|
||||||
import { visit } from "@ember/test-helpers";
|
|
||||||
import { cloneJSON } from "discourse-common/lib/object";
|
|
||||||
import topicFixtures from "discourse/tests/fixtures/topic";
|
|
||||||
|
|
||||||
acceptance("Last Visited Topic Focus", function (needs) {
|
|
||||||
needs.pretender((server, helper) => {
|
|
||||||
const fixture = cloneJSON(topicFixtures["/t/54077.json"]);
|
|
||||||
fixture.id = 11996;
|
|
||||||
fixture.slug =
|
|
||||||
"its-really-hard-to-navigate-the-create-topic-reply-pane-with-the-keyboard";
|
|
||||||
server.get("/t/11996.json", () => helper.response(fixture));
|
|
||||||
});
|
|
||||||
test("last visited topic receives focus when you return back to the topic list", async function (assert) {
|
|
||||||
await visit("/");
|
|
||||||
await visit(
|
|
||||||
"/t/its-really-hard-to-navigate-the-create-topic-reply-pane-with-the-keyboard/11996"
|
|
||||||
);
|
|
||||||
await visit("/");
|
|
||||||
const visitedTopicTitle = query(
|
|
||||||
'.topic-list-body tr[data-topic-id="11996"] .main-link'
|
|
||||||
);
|
|
||||||
assert.ok(visitedTopicTitle.classList.contains("focused"));
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -34,6 +34,10 @@ module PageObjects
|
||||||
find("#{TOPIC_LIST_BODY_SELECTOR} a", text: title).click
|
find("#{TOPIC_LIST_BODY_SELECTOR} a", text: title).click
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def visit_topic(topic)
|
||||||
|
find("#{topic_list_item_class(topic)} a.raw-topic-link").click
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def topic_list_item_class(topic)
|
def topic_list_item_class(topic)
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
describe "Topic list focus", type: :system do
|
||||||
|
let!(:topics) { Fabricate.times(10, :post).map(&:topic) }
|
||||||
|
|
||||||
|
before { Fabricate(:admin) }
|
||||||
|
|
||||||
|
let(:discovery) { PageObjects::Pages::Discovery.new }
|
||||||
|
let(:topic) { PageObjects::Pages::Topic.new }
|
||||||
|
|
||||||
|
def focussed_topic_id
|
||||||
|
page.evaluate_script(
|
||||||
|
"document.activeElement.closest('.topic-list-item')?.dataset.topicId",
|
||||||
|
)&.to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
it "refocusses last clicked topic when going back to topic list" do
|
||||||
|
visit("/")
|
||||||
|
expect(page).to have_css("body.navigation-topics")
|
||||||
|
expect(discovery.topic_list).to have_topics
|
||||||
|
|
||||||
|
# Click a topic
|
||||||
|
discovery.topic_list.visit_topic(topics[5])
|
||||||
|
expect(topic).to have_topic_title(topics[5].title)
|
||||||
|
|
||||||
|
# Going back to the topic-list should re-focus
|
||||||
|
page.go_back
|
||||||
|
expect(page).to have_css("body.navigation-topics")
|
||||||
|
expect(focussed_topic_id).to eq(topics[5].id)
|
||||||
|
|
||||||
|
# Click topic again
|
||||||
|
discovery.topic_list.visit_topic(topics[5])
|
||||||
|
expect(topic).to have_topic_title(topics[5].title)
|
||||||
|
|
||||||
|
# Visiting a topic list another way should not focus
|
||||||
|
find(".sidebar-section-link[data-link-name='everything']").click
|
||||||
|
expect(page).to have_css("body.navigation-topics")
|
||||||
|
expect(focussed_topic_id).to eq(nil)
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue