mirror of
https://github.com/discourse/discourse.git
synced 2025-03-23 03:45:43 +08:00
FIX: Keep track of suggestion updates during scrolling and navigation. (#23190)
This PR changes how we track which lists are available for a topic and how we decide which is the active one. The new approach centralizes everything in the service, and exposes functions for adding/removing a list, which each calls via `did-insert/will-destroy` modifiers. It makes it much easier to track and update state when navigated to another topic or PM, ensuring things get updated correctly.
This commit is contained in:
parent
a3410e7dc3
commit
7d0e2b9e7b
@ -1,14 +1,15 @@
|
||||
<div class="more-topics__container" {{did-insert this.buildListPills}}>
|
||||
<div class="more-topics__container">
|
||||
{{#unless this.singleList}}
|
||||
<div class="row">
|
||||
<ul class="nav nav-pills">
|
||||
{{#each this.availablePills as |pill|}}
|
||||
{{#each this.availableTabs as |tab|}}
|
||||
<li>
|
||||
<DButton
|
||||
@translatedTitle={{pill.name}}
|
||||
@translatedLabel={{pill.name}}
|
||||
@class={{if pill.selected "active"}}
|
||||
@action={{action "rememberTopicListPreference" pill.id}}
|
||||
@translatedTitle={{tab.name}}
|
||||
@translatedLabel={{tab.name}}
|
||||
@class={{if (eq tab.id this.selectedTab) "active"}}
|
||||
@action={{action "rememberTopicListPreference" tab.id}}
|
||||
@icon={{tab.icon}}
|
||||
/>
|
||||
</li>
|
||||
{{/each}}
|
||||
|
@ -1,8 +1,6 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { next } from "@ember/runloop";
|
||||
import { action, computed } from "@ember/object";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import I18n from "I18n";
|
||||
import { categoryBadgeHTML } from "discourse/helpers/category-link";
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
@ -15,59 +13,24 @@ export default class MoreTopics extends Component {
|
||||
@service topicTrackingState;
|
||||
@service currentUser;
|
||||
|
||||
@tracked availablePills = [];
|
||||
@tracked singleList = false;
|
||||
|
||||
@action
|
||||
rememberTopicListPreference(value) {
|
||||
// Don't change the preference when selecting related PMs.
|
||||
// It messes with the topics pref.
|
||||
const rememberPref = value !== "related-messages";
|
||||
|
||||
this.moreTopicsPreferenceTracking.updatePreference(value, rememberPref);
|
||||
|
||||
this.buildListPills();
|
||||
this.moreTopicsPreferenceTracking.updatePreference(value);
|
||||
}
|
||||
|
||||
@action
|
||||
buildListPills() {
|
||||
next(() => {
|
||||
const pills = Array.from(
|
||||
document.querySelectorAll(".more-topics__list")
|
||||
).map((topicList) => {
|
||||
return {
|
||||
name: topicList.dataset.mobileTitle,
|
||||
id: topicList.dataset.listId,
|
||||
};
|
||||
});
|
||||
@computed("moreTopicsPreferenceTracking.topicLists")
|
||||
get singleList() {
|
||||
return this.availableTabs.length === 1;
|
||||
}
|
||||
|
||||
if (pills.length === 0) {
|
||||
return;
|
||||
} else if (pills.length === 1) {
|
||||
this.singleList = true;
|
||||
}
|
||||
@computed("moreTopicsPreferenceTracking.selectedTab")
|
||||
get selectedTab() {
|
||||
return this.moreTopicsPreferenceTracking.selectedTab;
|
||||
}
|
||||
|
||||
let preference = this.moreTopicsPreferenceTracking.preference;
|
||||
// Scenario where we have a preference, but there
|
||||
// are no more elements in it.
|
||||
const listPresent = pills.find((pill) => pill.id === preference);
|
||||
|
||||
if (!listPresent) {
|
||||
const rememberPref = false;
|
||||
|
||||
this.moreTopicsPreferenceTracking.updatePreference(
|
||||
pills[0].id,
|
||||
rememberPref
|
||||
);
|
||||
preference = pills[0].id;
|
||||
}
|
||||
|
||||
pills.forEach((pill) => {
|
||||
pill.selected = pill.id === preference;
|
||||
});
|
||||
|
||||
this.availablePills = pills;
|
||||
});
|
||||
@computed("moreTopicsPreferenceTracking.topicLists")
|
||||
get availableTabs() {
|
||||
return this.moreTopicsPreferenceTracking.topicLists;
|
||||
}
|
||||
|
||||
@computed(
|
||||
|
@ -3,8 +3,8 @@
|
||||
class="more-topics__list {{if this.hidden 'hidden'}}"
|
||||
role="complementary"
|
||||
aria-labelledby="related-messages-title"
|
||||
data-mobile-title={{i18n "related_messages.pill"}}
|
||||
data-list-id={{this.listId}}
|
||||
{{did-insert this.registerList}}
|
||||
{{will-destroy this.removeList}}
|
||||
>
|
||||
<h3 id="related-messages-title" class="more-topics__list-title">
|
||||
{{i18n "related_messages.title"}}
|
||||
|
@ -1,7 +1,8 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { computed } from "@ember/object";
|
||||
import { action, computed } from "@ember/object";
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
import { inject as service } from "@ember/service";
|
||||
import I18n from "I18n";
|
||||
|
||||
export default class RelatedMessages extends Component {
|
||||
@service moreTopicsPreferenceTracking;
|
||||
@ -9,9 +10,22 @@ export default class RelatedMessages extends Component {
|
||||
|
||||
listId = "related-Messages";
|
||||
|
||||
@computed("moreTopicsPreferenceTracking.preference")
|
||||
@computed("moreTopicsPreferenceTracking.selectedTab")
|
||||
get hidden() {
|
||||
return this.moreTopicsPreferenceTracking.preference !== this.listId;
|
||||
return this.moreTopicsPreferenceTracking.selectedTab !== this.listId;
|
||||
}
|
||||
|
||||
@action
|
||||
registerList() {
|
||||
this.moreTopicsPreferenceTracking.registerTopicList({
|
||||
name: I18n.t("related_messages.pill"),
|
||||
id: this.listId,
|
||||
});
|
||||
}
|
||||
|
||||
@action
|
||||
removeList() {
|
||||
this.moreTopicsPreferenceTracking.removeTopicList(this.listId);
|
||||
}
|
||||
|
||||
get targetUser() {
|
||||
|
@ -3,8 +3,8 @@
|
||||
class="more-topics__list {{if this.hidden 'hidden'}}"
|
||||
role="complementary"
|
||||
aria-labelledby="suggested-topics-title"
|
||||
data-mobile-title={{i18n "suggested_topics.pill"}}
|
||||
data-list-id={{this.listId}}
|
||||
{{did-insert this.registerList}}
|
||||
{{will-destroy this.removeList}}
|
||||
>
|
||||
<UserTip @id="suggested_topics" @selector=".user-tip-reference" />
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { computed } from "@ember/object";
|
||||
import { action, computed } from "@ember/object";
|
||||
import { inject as service } from "@ember/service";
|
||||
import I18n from "I18n";
|
||||
|
||||
export default class SuggestedTopics extends Component {
|
||||
@service moreTopicsPreferenceTracking;
|
||||
@ -17,8 +18,21 @@ export default class SuggestedTopics extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
@computed("moreTopicsPreferenceTracking.preference")
|
||||
@computed("moreTopicsPreferenceTracking.selectedTab")
|
||||
get hidden() {
|
||||
return this.moreTopicsPreferenceTracking.preference !== this.listId;
|
||||
return this.moreTopicsPreferenceTracking.selectedTab !== this.listId;
|
||||
}
|
||||
|
||||
@action
|
||||
registerList() {
|
||||
this.moreTopicsPreferenceTracking.registerTopicList({
|
||||
name: I18n.t("suggested_topics.pill"),
|
||||
id: this.listId,
|
||||
});
|
||||
}
|
||||
|
||||
@action
|
||||
removeList() {
|
||||
this.moreTopicsPreferenceTracking.removeTopicList(this.listId);
|
||||
}
|
||||
}
|
||||
|
@ -6,18 +6,49 @@ const TOPIC_LIST_PREFERENCE_KEY = "more-topics-list-preference";
|
||||
export default class MoreTopicsPreferenceTracking extends Service {
|
||||
@service keyValueStore;
|
||||
|
||||
@tracked preference;
|
||||
@tracked selectedTab = null;
|
||||
@tracked topicLists = [];
|
||||
|
||||
memoryTab = null;
|
||||
|
||||
init() {
|
||||
super.init(...arguments);
|
||||
this.preference = this.keyValueStore.get(TOPIC_LIST_PREFERENCE_KEY);
|
||||
this.memoryTab = this.keyValueStore.get(TOPIC_LIST_PREFERENCE_KEY);
|
||||
}
|
||||
|
||||
updatePreference(value, rememberPref = true) {
|
||||
updatePreference(value) {
|
||||
// Don't change the preference when selecting related PMs.
|
||||
// It messes with the topics pref.
|
||||
const rememberPref = value !== "related-messages";
|
||||
|
||||
if (rememberPref) {
|
||||
this.keyValueStore.set({ key: TOPIC_LIST_PREFERENCE_KEY, value });
|
||||
this.memoryTab = value;
|
||||
}
|
||||
|
||||
this.preference = value;
|
||||
this.selectedTab = value;
|
||||
}
|
||||
|
||||
registerTopicList(item) {
|
||||
// We have a preference stored and the list exists.
|
||||
if (this.memoryTab && this.memoryTab === item.id) {
|
||||
this.selectedTab = item.id;
|
||||
}
|
||||
|
||||
// Use the first list as a default. Future lists may override this
|
||||
// if they match the stored preference.
|
||||
if (!this.selectedTab) {
|
||||
this.selectedTab = item.id;
|
||||
}
|
||||
|
||||
this.topicLists = [...this.topicLists, item];
|
||||
}
|
||||
|
||||
removeTopicList(itemId) {
|
||||
this.topicLists = this.topicLists.filter((item) => item.id !== itemId);
|
||||
|
||||
if (this.selectedTab === itemId) {
|
||||
this.selectedTab = this.topicLists[0]?.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,10 @@
|
||||
.btn {
|
||||
padding: 0.5em 0.65em;
|
||||
}
|
||||
|
||||
.btn.active .d-icon {
|
||||
color: var(--primary-low);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user