mirror of
https://github.com/discourse/discourse.git
synced 2025-03-20 15:15:31 +08:00
FEATURE: New/unread messages count in experimental sidebar (#17117)
* FEATURE: Expand messages filter links when viewing private messages. * FEATURE: New/unread messages count in experimental sidebar
This commit is contained in:
parent
b09cce6897
commit
0b8e6adabe
@ -2,13 +2,14 @@ import { cached } from "@glimmer/tracking";
|
||||
|
||||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
import GlimmerComponent from "discourse/components/glimmer";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
import GroupMessageSectionLink from "discourse/lib/sidebar/messages-section/group-message-section-link";
|
||||
import PersonalMessageSectionLink from "discourse/lib/sidebar/messages-section/personal-message-section-link";
|
||||
|
||||
export const INBOX = "inbox";
|
||||
const UNREAD = "unread";
|
||||
export const UNREAD = "unread";
|
||||
const SENT = "sent";
|
||||
const NEW = "new";
|
||||
export const NEW = "new";
|
||||
const ARCHIVE = "archive";
|
||||
|
||||
export const PERSONAL_MESSAGES_INBOX_FILTERS = [
|
||||
@ -30,6 +31,24 @@ export default class SidebarMessagesSection extends GlimmerComponent {
|
||||
this,
|
||||
this._refreshSectionLinksDisplayState
|
||||
);
|
||||
|
||||
this.pmTopicTrackingState
|
||||
.startTracking()
|
||||
.then(this._refreshSectionLinkCounts);
|
||||
|
||||
this._pmTopicTrackingStateKey = "messages-section";
|
||||
|
||||
this.pmTopicTrackingState.onStateChange(
|
||||
this._pmTopicTrackingStateKey,
|
||||
this._refreshSectionLinkCounts
|
||||
);
|
||||
}
|
||||
|
||||
@bind
|
||||
_refreshSectionLinkCounts() {
|
||||
for (const sectionLink of this.allSectionLinks) {
|
||||
sectionLink.refreshCount();
|
||||
}
|
||||
}
|
||||
|
||||
willDestroy() {
|
||||
@ -38,6 +57,11 @@ export default class SidebarMessagesSection extends GlimmerComponent {
|
||||
this,
|
||||
this._refreshSectionLinksDisplayState
|
||||
);
|
||||
|
||||
this.pmTopicTrackingState.offStateChange(
|
||||
this._pmTopicTrackingStateKey,
|
||||
this._refreshSectionLinkCounts
|
||||
);
|
||||
}
|
||||
|
||||
_refreshSectionLinksDisplayState({
|
||||
@ -81,6 +105,7 @@ export default class SidebarMessagesSection extends GlimmerComponent {
|
||||
new PersonalMessageSectionLink({
|
||||
currentUser: this.currentUser,
|
||||
type,
|
||||
pmTopicTrackingState: this.pmTopicTrackingState,
|
||||
})
|
||||
);
|
||||
});
|
||||
@ -99,6 +124,7 @@ export default class SidebarMessagesSection extends GlimmerComponent {
|
||||
group,
|
||||
type: groupMessageLink,
|
||||
currentUser: this.currentUser,
|
||||
pmTopicTrackingState: this.pmTopicTrackingState,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
@ -40,6 +40,10 @@ export default class GroupMessageSectionLink extends MessageSectionLink {
|
||||
get text() {
|
||||
if (this._isInbox) {
|
||||
return this.group.name;
|
||||
} else if (this.count > 0) {
|
||||
return I18n.t(`sidebar.sections.messages.links.${this.type}_with_count`, {
|
||||
count: this.count,
|
||||
});
|
||||
} else {
|
||||
return I18n.t(`sidebar.sections.messages.links.${this.type}`);
|
||||
}
|
||||
|
@ -1,18 +1,42 @@
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
|
||||
import { INBOX } from "discourse/components/sidebar/messages-section";
|
||||
import {
|
||||
INBOX,
|
||||
NEW,
|
||||
UNREAD,
|
||||
} from "discourse/components/sidebar/messages-section";
|
||||
|
||||
export default class MessageSectionLink {
|
||||
@tracked shouldDisplay = this._isInbox;
|
||||
@tracked count = 0;
|
||||
|
||||
constructor({ group, currentUser, type }) {
|
||||
constructor({ group, currentUser, type, pmTopicTrackingState }) {
|
||||
this.group = group;
|
||||
this.currentUser = currentUser;
|
||||
this.type = type;
|
||||
this.pmTopicTrackingState = pmTopicTrackingState;
|
||||
}
|
||||
|
||||
refreshCount() {
|
||||
this._refreshCount();
|
||||
}
|
||||
|
||||
_refreshCount() {
|
||||
if (this.shouldDisplay && this._shouldTrack) {
|
||||
this.count = this.pmTopicTrackingState.lookupCount(this.type, {
|
||||
inboxFilter: this.group ? "group" : "user",
|
||||
groupName: this.group?.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
set setDisplayState(value) {
|
||||
const changed = this.shouldDisplay !== value;
|
||||
this.shouldDisplay = value;
|
||||
|
||||
if (changed) {
|
||||
this._refreshCount();
|
||||
}
|
||||
}
|
||||
|
||||
get inboxFilter() {
|
||||
@ -43,4 +67,8 @@ export default class MessageSectionLink {
|
||||
get _isInbox() {
|
||||
return this.type === INBOX;
|
||||
}
|
||||
|
||||
get _shouldTrack() {
|
||||
return this.type === NEW || this.type === UNREAD;
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,13 @@ export default class PersonalMessageSectionLink extends MessageSectionLink {
|
||||
}
|
||||
|
||||
get text() {
|
||||
return I18n.t(`sidebar.sections.messages.links.${this.type}`);
|
||||
if (this.count > 0) {
|
||||
return I18n.t(`sidebar.sections.messages.links.${this.type}_with_count`, {
|
||||
count: this.count,
|
||||
});
|
||||
} else {
|
||||
return I18n.t(`sidebar.sections.messages.links.${this.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
pageChanged({ currentRouteName, privateMessageTopic }) {
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { Promise } from "rsvp";
|
||||
|
||||
import EmberObject from "@ember/object";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { bind, on } from "discourse-common/utils/decorators";
|
||||
@ -25,16 +27,20 @@ const PrivateMessageTopicTrackingState = EmberObject.extend({
|
||||
this.statesModificationCounter = 0;
|
||||
this.isTracking = false;
|
||||
this.newIncoming = [];
|
||||
this.stateChangeCallbacks = {};
|
||||
this.stateChangeCallbacks = new Map();
|
||||
},
|
||||
|
||||
onStateChange(name, callback) {
|
||||
this.stateChangeCallbacks[name] = callback;
|
||||
onStateChange(key, callback) {
|
||||
this.stateChangeCallbacks.set(key, callback);
|
||||
},
|
||||
|
||||
offStateChange(key) {
|
||||
this.stateChangeCallbacks.delete(key);
|
||||
},
|
||||
|
||||
startTracking() {
|
||||
if (this.isTracking) {
|
||||
return;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
this._establishChannels();
|
||||
@ -46,13 +52,13 @@ const PrivateMessageTopicTrackingState = EmberObject.extend({
|
||||
|
||||
_establishChannels() {
|
||||
this.messageBus.subscribe(
|
||||
this._userChannel(),
|
||||
this.userChannel(),
|
||||
this._processMessage.bind(this)
|
||||
);
|
||||
|
||||
this.currentUser.groupsWithMessages?.forEach((group) => {
|
||||
this.messageBus.subscribe(
|
||||
this._groupChannel(group.id),
|
||||
this.groupChannel(group.id),
|
||||
this._processMessage.bind(this)
|
||||
);
|
||||
});
|
||||
@ -111,11 +117,11 @@ const PrivateMessageTopicTrackingState = EmberObject.extend({
|
||||
return this.states.get(topicId);
|
||||
},
|
||||
|
||||
_userChannel() {
|
||||
userChannel() {
|
||||
return `${this.CHANNEL_PREFIX}/user/${this.currentUser.id}`;
|
||||
},
|
||||
|
||||
_groupChannel(groupId) {
|
||||
groupChannel(groupId) {
|
||||
return `${this.CHANNEL_PREFIX}/group/${groupId}`;
|
||||
},
|
||||
|
||||
@ -263,7 +269,7 @@ const PrivateMessageTopicTrackingState = EmberObject.extend({
|
||||
|
||||
_afterStateChange() {
|
||||
this.incrementProperty("statesModificationCounter");
|
||||
Object.values(this.stateChangeCallbacks).forEach((callback) => callback());
|
||||
this.stateChangeCallbacks.forEach((callback) => callback());
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1,13 +1,17 @@
|
||||
import { test } from "qunit";
|
||||
import I18n from "I18n";
|
||||
|
||||
import { click, currentURL, visit } from "@ember/test-helpers";
|
||||
import { click, currentURL, settled, visit } from "@ember/test-helpers";
|
||||
|
||||
import {
|
||||
acceptance,
|
||||
exists,
|
||||
publishToMessageBus,
|
||||
query,
|
||||
queryAll,
|
||||
updateCurrentUser,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import { NotificationLevels } from "discourse/lib/notification-levels";
|
||||
|
||||
acceptance(
|
||||
"Sidebar - Messages Section - enable_personal_messages disabled",
|
||||
@ -355,5 +359,192 @@ acceptance(
|
||||
"foo_group messages inbox filter links are not shown"
|
||||
);
|
||||
});
|
||||
|
||||
test("new and unread counts for group messages", async function (assert) {
|
||||
updateCurrentUser({
|
||||
groups: [
|
||||
{
|
||||
id: 1,
|
||||
name: "group1",
|
||||
has_messages: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await visit("/");
|
||||
|
||||
const pmTopicTrackingState = this.container.lookup(
|
||||
"pm-topic-tracking-state:main"
|
||||
);
|
||||
|
||||
publishToMessageBus(pmTopicTrackingState.groupChannel(1), {
|
||||
topic_id: 1,
|
||||
message_type: "unread",
|
||||
payload: {
|
||||
last_read_post_number: 1,
|
||||
highest_post_number: 2,
|
||||
notification_level: NotificationLevels.TRACKING,
|
||||
group_ids: [1],
|
||||
},
|
||||
});
|
||||
|
||||
publishToMessageBus(pmTopicTrackingState.groupChannel(1), {
|
||||
topic_id: 2,
|
||||
message_type: "new_topic",
|
||||
payload: {
|
||||
last_read_post_number: null,
|
||||
highest_post_number: 1,
|
||||
notification_level: NotificationLevels.TRACKING,
|
||||
group_ids: [1],
|
||||
},
|
||||
});
|
||||
|
||||
await click(
|
||||
".sidebar-section-messages .sidebar-section-link-group-messages-inbox.group1"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
query(
|
||||
".sidebar-section-messages .sidebar-section-link-group-messages-unread.group1"
|
||||
).textContent.trim(),
|
||||
I18n.t("sidebar.sections.messages.links.unread_with_count", {
|
||||
count: 1,
|
||||
}),
|
||||
"displays 1 count for group1 unread inbox filter link"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
query(
|
||||
".sidebar-section-messages .sidebar-section-link-group-messages-new.group1"
|
||||
).textContent.trim(),
|
||||
I18n.t("sidebar.sections.messages.links.new_with_count", {
|
||||
count: 1,
|
||||
}),
|
||||
"displays 1 count for group1 new inbox filter link"
|
||||
);
|
||||
|
||||
publishToMessageBus(pmTopicTrackingState.groupChannel(1), {
|
||||
topic_id: 2,
|
||||
message_type: "read",
|
||||
payload: {
|
||||
last_read_post_number: 1,
|
||||
highest_post_number: 1,
|
||||
notification_level: NotificationLevels.TRACKING,
|
||||
group_ids: [1],
|
||||
},
|
||||
});
|
||||
|
||||
await settled();
|
||||
|
||||
assert.strictEqual(
|
||||
query(
|
||||
".sidebar-section-messages .sidebar-section-link-group-messages-new.group1"
|
||||
).textContent.trim(),
|
||||
I18n.t("sidebar.sections.messages.links.new"),
|
||||
"removes count for group1 new inbox filter link"
|
||||
);
|
||||
});
|
||||
|
||||
test("new and unread counts for personal messages", async function (assert) {
|
||||
await visit("/");
|
||||
|
||||
const pmTopicTrackingState = this.container.lookup(
|
||||
"pm-topic-tracking-state:main"
|
||||
);
|
||||
|
||||
publishToMessageBus(pmTopicTrackingState.userChannel(), {
|
||||
topic_id: 1,
|
||||
message_type: "unread",
|
||||
payload: {
|
||||
last_read_post_number: 1,
|
||||
highest_post_number: 2,
|
||||
notification_level: NotificationLevels.TRACKING,
|
||||
group_ids: [],
|
||||
},
|
||||
});
|
||||
|
||||
await settled();
|
||||
|
||||
await click(
|
||||
".sidebar-section-messages .sidebar-section-link-personal-messages-inbox"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
query(
|
||||
".sidebar-section-messages .sidebar-section-link-personal-messages-unread"
|
||||
).textContent.trim(),
|
||||
I18n.t("sidebar.sections.messages.links.unread_with_count", {
|
||||
count: 1,
|
||||
}),
|
||||
"displays 1 count for the unread inbox filter link"
|
||||
);
|
||||
|
||||
publishToMessageBus(pmTopicTrackingState.userChannel(), {
|
||||
topic_id: 2,
|
||||
message_type: "unread",
|
||||
payload: {
|
||||
last_read_post_number: 1,
|
||||
highest_post_number: 2,
|
||||
notification_level: NotificationLevels.TRACKING,
|
||||
group_ids: [],
|
||||
},
|
||||
});
|
||||
|
||||
await settled();
|
||||
|
||||
assert.strictEqual(
|
||||
query(
|
||||
".sidebar-section-messages .sidebar-section-link-personal-messages-unread"
|
||||
).textContent.trim(),
|
||||
I18n.t("sidebar.sections.messages.links.unread_with_count", {
|
||||
count: 2,
|
||||
}),
|
||||
"displays 2 count for the unread inbox filter link"
|
||||
);
|
||||
|
||||
publishToMessageBus(pmTopicTrackingState.userChannel(), {
|
||||
topic_id: 3,
|
||||
message_type: "new_topic",
|
||||
payload: {
|
||||
last_read_post_number: null,
|
||||
highest_post_number: 1,
|
||||
notification_level: NotificationLevels.TRACKING,
|
||||
group_ids: [],
|
||||
},
|
||||
});
|
||||
|
||||
await settled();
|
||||
|
||||
assert.strictEqual(
|
||||
query(
|
||||
".sidebar-section-messages .sidebar-section-link-personal-messages-new"
|
||||
).textContent.trim(),
|
||||
I18n.t("sidebar.sections.messages.links.new_with_count", {
|
||||
count: 1,
|
||||
}),
|
||||
"displays 1 count for the new inbox filter link"
|
||||
);
|
||||
|
||||
publishToMessageBus(pmTopicTrackingState.userChannel(), {
|
||||
topic_id: 3,
|
||||
message_type: "read",
|
||||
payload: {
|
||||
last_read_post_number: 1,
|
||||
highest_post_number: 1,
|
||||
notification_level: NotificationLevels.TRACKING,
|
||||
group_ids: [],
|
||||
},
|
||||
});
|
||||
|
||||
await settled();
|
||||
|
||||
assert.strictEqual(
|
||||
query(
|
||||
".sidebar-section-messages .sidebar-section-link-personal-messages-new"
|
||||
).textContent.trim(),
|
||||
I18n.t("sidebar.sections.messages.links.new"),
|
||||
"removes the count from the new inbox filter link"
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
@ -4051,7 +4051,9 @@ en:
|
||||
inbox: "Inbox"
|
||||
sent: "Sent"
|
||||
new: "New"
|
||||
new_with_count: "New (%{count})"
|
||||
unread: "Unread"
|
||||
unread_with_count: "Unread (%{count})"
|
||||
archive: "Archive"
|
||||
tags:
|
||||
no_tracked_tags: "You are not tracking any tags."
|
||||
|
Loading…
x
Reference in New Issue
Block a user