DEV: Include unread topics in New topic lists and link to it in sidebar (#20432)
This commit introduces a few experimental changes to the New topics list and "Everything" link in the sidebar: 1. Make the New topics list include unread topics 2. Make the Everything section in the sidebar link to the New topics list (`/new`) 3. Remove "unread" or "new" text next to the count and keep the count 4. The count is a sum of new and unread topics counts All of these of changes are behind an off-by-default feature flag. I've not written extensive tests for these changes because they're highly experimental. Internal topic: t/77234.
This commit is contained in:
parent
badd40090f
commit
a509441148
|
@ -150,7 +150,6 @@ const controllerOpts = {
|
|||
hasTopics: gt("model.topics.length", 0),
|
||||
allLoaded: empty("model.more_topics_url"),
|
||||
latest: endWith("model.filter", "latest"),
|
||||
new: endWith("model.filter", "new"),
|
||||
top: endWith("model.filter", "top"),
|
||||
yearly: equal("period", "yearly"),
|
||||
quarterly: equal("period", "quarterly"),
|
||||
|
@ -158,6 +157,11 @@ const controllerOpts = {
|
|||
weekly: equal("period", "weekly"),
|
||||
daily: equal("period", "daily"),
|
||||
|
||||
@discourseComputed("model.filter")
|
||||
new(filter) {
|
||||
return filter?.endsWith("new") && !this.currentUser?.new_new_view_enabled;
|
||||
},
|
||||
|
||||
@discourseComputed("allLoaded", "model.topics.length")
|
||||
footerMessage(allLoaded, topicsLength) {
|
||||
if (!allLoaded) {
|
||||
|
|
|
@ -9,6 +9,7 @@ export default class EverythingSectionLink extends BaseSectionLink {
|
|||
@tracked totalNew = 0;
|
||||
@tracked hideCount =
|
||||
this.currentUser?.sidebarListDestination !== UNREAD_LIST_DESTINATION;
|
||||
linkToNew = !!this.currentUser?.new_new_view_enabled;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
@ -26,7 +27,7 @@ export default class EverythingSectionLink extends BaseSectionLink {
|
|||
|
||||
this.totalUnread = this.topicTrackingState.countUnread();
|
||||
|
||||
if (this.totalUnread === 0) {
|
||||
if (this.totalUnread === 0 || this.linkToNew) {
|
||||
this.totalNew = this.topicTrackingState.countNew();
|
||||
}
|
||||
}
|
||||
|
@ -48,10 +49,17 @@ export default class EverythingSectionLink extends BaseSectionLink {
|
|||
}
|
||||
|
||||
get currentWhen() {
|
||||
return "discovery.latest discovery.new discovery.unread discovery.top";
|
||||
if (this.linkToNew) {
|
||||
return "discovery.new";
|
||||
} else {
|
||||
return "discovery.latest discovery.new discovery.unread discovery.top";
|
||||
}
|
||||
}
|
||||
|
||||
get badgeText() {
|
||||
if (this.linkToNew && this.#unreadAndNewCount > 0) {
|
||||
return this.#unreadAndNewCount.toString();
|
||||
}
|
||||
if (this.hideCount) {
|
||||
return;
|
||||
}
|
||||
|
@ -63,13 +71,15 @@ export default class EverythingSectionLink extends BaseSectionLink {
|
|||
return I18n.t("sidebar.new_count", {
|
||||
count: this.totalNew,
|
||||
});
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
get route() {
|
||||
if (this.currentUser?.sidebarListDestination === UNREAD_LIST_DESTINATION) {
|
||||
if (this.linkToNew) {
|
||||
return "discovery.new";
|
||||
} else if (
|
||||
this.currentUser?.sidebarListDestination === UNREAD_LIST_DESTINATION
|
||||
) {
|
||||
if (this.totalUnread > 0) {
|
||||
return "discovery.unread";
|
||||
}
|
||||
|
@ -93,8 +103,16 @@ export default class EverythingSectionLink extends BaseSectionLink {
|
|||
}
|
||||
|
||||
get suffixValue() {
|
||||
if (this.hideCount && (this.totalUnread || this.totalNew)) {
|
||||
if (
|
||||
this.hideCount &&
|
||||
(this.totalUnread || this.totalNew) &&
|
||||
!this.linkToNew
|
||||
) {
|
||||
return "circle";
|
||||
}
|
||||
}
|
||||
|
||||
get #unreadAndNewCount() {
|
||||
return this.totalUnread + this.totalNew;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -249,6 +249,10 @@ NavItem.reopenClass({
|
|||
}
|
||||
let items = args.siteSettings.top_menu.split("|");
|
||||
|
||||
const user = getOwner(this).lookup("service:current-user");
|
||||
if (user?.new_new_view_enabled) {
|
||||
items = items.reject((item) => item === "unread");
|
||||
}
|
||||
const filterType = (args.filterMode || "").split("/").pop();
|
||||
|
||||
if (!items.some((i) => filterType === i)) {
|
||||
|
|
|
@ -709,12 +709,21 @@ const TopicTrackingState = EmberObject.extend({
|
|||
let categoryId = category ? get(category, "id") : null;
|
||||
|
||||
if (type === "new") {
|
||||
return this.countNew({
|
||||
let count = this.countNew({
|
||||
categoryId,
|
||||
tagId,
|
||||
noSubcategories,
|
||||
customFilterFn,
|
||||
});
|
||||
if (this.currentUser?.new_new_view_enabled) {
|
||||
count += this.countUnread({
|
||||
categoryId,
|
||||
tagId,
|
||||
noSubcategories,
|
||||
customFilterFn,
|
||||
});
|
||||
}
|
||||
return count;
|
||||
} else if (type === "unread") {
|
||||
return this.countUnread({
|
||||
categoryId,
|
||||
|
@ -790,8 +799,14 @@ const TopicTrackingState = EmberObject.extend({
|
|||
// for a particular seen topic has not yet reached the server.
|
||||
_fixDelayedServerState(list, filter) {
|
||||
for (let index = list.topics.length - 1; index >= 0; index--) {
|
||||
const state = this.findState(list.topics[index].id);
|
||||
if (state && state.last_read_post_number > 0) {
|
||||
const topic = list.topics[index];
|
||||
const state = this.findState(topic.id);
|
||||
if (
|
||||
state &&
|
||||
state.last_read_post_number > 0 &&
|
||||
(topic.last_read_post_number === 0 ||
|
||||
!this.currentUser?.new_new_view_enabled)
|
||||
) {
|
||||
if (filter === "new") {
|
||||
list.topics.splice(index, 1);
|
||||
} else {
|
||||
|
|
|
@ -1812,6 +1812,10 @@ class User < ActiveRecord::Base
|
|||
!SiteSetting.legacy_navigation_menu? || SiteSetting.enable_new_notifications_menu
|
||||
end
|
||||
|
||||
def new_new_view_enabled?
|
||||
in_any_groups?(SiteSetting.experimental_new_new_view_groups_map)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def badge_grant
|
||||
|
|
|
@ -69,7 +69,8 @@ class CurrentUserSerializer < BasicUserSerializer
|
|||
:sidebar_category_ids,
|
||||
:sidebar_list_destination,
|
||||
:sidebar_sections,
|
||||
:custom_sidebar_sections_enabled
|
||||
:custom_sidebar_sections_enabled,
|
||||
:new_new_view_enabled?
|
||||
|
||||
delegate :user_stat, to: :object, private: true
|
||||
delegate :any_posts, :draft_count, :pending_posts_count, :read_faq?, to: :user_stat
|
||||
|
|
|
@ -2398,6 +2398,7 @@ en:
|
|||
default_sidebar_tags: "Selected tags will be displayed under Sidebar's Tags section by default."
|
||||
enable_new_notifications_menu: "Enables the new notifications menu for the legacy navigation menu."
|
||||
enable_experimental_hashtag_autocomplete: "EXPERIMENTAL: Use the new #hashtag autocompletion system for categories and tags that renders the selected item differently and has improved search"
|
||||
experimental_new_new_view_groups: "EXPERIMENTAL: Enable a new topics list that combines unread and new topics and make the \"Everything\" link in the sidebar link to it."
|
||||
|
||||
errors:
|
||||
invalid_css_color: "Invalid color. Enter a color name or hex value."
|
||||
|
|
|
@ -2073,6 +2073,13 @@ developer:
|
|||
client: true
|
||||
default: false
|
||||
hidden: true
|
||||
experimental_new_new_view_groups:
|
||||
client: true
|
||||
type: group_list
|
||||
list_type: compact
|
||||
default: ""
|
||||
allow_any: false
|
||||
refresh: true
|
||||
|
||||
navigation:
|
||||
navigation_menu:
|
||||
|
|
|
@ -267,7 +267,11 @@ class TopicQuery
|
|||
end
|
||||
|
||||
def list_new
|
||||
create_list(:new, { unordered: true }, new_results)
|
||||
if @user&.new_new_view_enabled?
|
||||
create_list(:new, { unordered: true }, new_and_unread_results)
|
||||
else
|
||||
create_list(:new, { unordered: true }, new_results)
|
||||
end
|
||||
end
|
||||
|
||||
def list_unread
|
||||
|
|
Loading…
Reference in New Issue