mirror of
https://github.com/discourse/discourse.git
synced 2025-06-06 13:06:56 +08:00
FEATURE: Sync user tips status between client (#19095)
The user attributes are not updated between clients and that is a problem with user tips because the same user tip will be displayed multiple times, once for every client.
This commit is contained in:
@ -0,0 +1,29 @@
|
|||||||
|
export default {
|
||||||
|
name: "user-tips",
|
||||||
|
after: "message-bus",
|
||||||
|
|
||||||
|
initialize(container) {
|
||||||
|
const currentUser = container.lookup("service:current-user");
|
||||||
|
if (!currentUser) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const messageBus = container.lookup("service:message-bus");
|
||||||
|
const site = container.lookup("service:site");
|
||||||
|
|
||||||
|
messageBus.subscribe("/user-tips", function (seenUserTips) {
|
||||||
|
currentUser.set("seen_popups", seenUserTips);
|
||||||
|
if (!currentUser.user_option) {
|
||||||
|
currentUser.set("user_option", {});
|
||||||
|
}
|
||||||
|
currentUser.set("user_option.seen_popups", seenUserTips);
|
||||||
|
(seenUserTips || []).forEach((userTipId) => {
|
||||||
|
currentUser.hideUserTipForever(
|
||||||
|
Object.keys(site.user_tips).find(
|
||||||
|
(id) => site.user_tips[id] === userTipId
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
@ -1173,27 +1173,28 @@ const User = RestModel.extend({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide any shown user tips.
|
// Hide user tips and maybe show the next one.
|
||||||
|
if (userTipId) {
|
||||||
|
hideUserTip(userTipId);
|
||||||
|
showNextUserTip();
|
||||||
|
} else {
|
||||||
|
hideAllUserTips();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update list of seen user tips.
|
||||||
let seenUserTips = this.seen_popups || [];
|
let seenUserTips = this.seen_popups || [];
|
||||||
if (userTipId) {
|
if (userTipId) {
|
||||||
if (seenUserTips.includes(userTips[userTipId])) {
|
if (seenUserTips.includes(userTips[userTipId])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hideUserTip(userTipId);
|
|
||||||
seenUserTips.push(userTips[userTipId]);
|
seenUserTips.push(userTips[userTipId]);
|
||||||
} else {
|
} else {
|
||||||
if (seenUserTips.includes(-1)) {
|
if (seenUserTips.includes(-1)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hideAllUserTips();
|
|
||||||
seenUserTips = [-1];
|
seenUserTips = [-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show next user tip in queue.
|
|
||||||
showNextUserTip();
|
|
||||||
|
|
||||||
// Save seen user tips on the server.
|
// Save seen user tips on the server.
|
||||||
if (!this.user_option) {
|
if (!this.user_option) {
|
||||||
this.set("user_option", {});
|
this.set("user_option", {});
|
||||||
|
@ -6,6 +6,7 @@ import { settled } from "@ember/test-helpers";
|
|||||||
import User from "discourse/models/user";
|
import User from "discourse/models/user";
|
||||||
import pretender, { response } from "discourse/tests/helpers/create-pretender";
|
import pretender, { response } from "discourse/tests/helpers/create-pretender";
|
||||||
import { getOwner } from "discourse-common/lib/get-owner";
|
import { getOwner } from "discourse-common/lib/get-owner";
|
||||||
|
import * as userTips from "discourse/lib/user-tips";
|
||||||
|
|
||||||
module("Unit | Model | user", function (hooks) {
|
module("Unit | Model | user", function (hooks) {
|
||||||
setupTest(hooks);
|
setupTest(hooks);
|
||||||
@ -199,12 +200,11 @@ module("Unit | Model | user", function (hooks) {
|
|||||||
test("hideUserTipForever() makes a single request", async function (assert) {
|
test("hideUserTipForever() makes a single request", async function (assert) {
|
||||||
const site = getOwner(this).lookup("service:site");
|
const site = getOwner(this).lookup("service:site");
|
||||||
site.set("user_tips", { first_notification: 1 });
|
site.set("user_tips", { first_notification: 1 });
|
||||||
|
|
||||||
const store = getOwner(this).lookup("service:store");
|
const store = getOwner(this).lookup("service:store");
|
||||||
const user = store.createRecord("user", { username: "test" });
|
const user = store.createRecord("user", { username: "eviltrout" });
|
||||||
|
|
||||||
let requestsCount = 0;
|
let requestsCount = 0;
|
||||||
pretender.put("/u/test.json", () => {
|
pretender.put("/u/eviltrout.json", () => {
|
||||||
requestsCount += 1;
|
requestsCount += 1;
|
||||||
return response(200, {
|
return response(200, {
|
||||||
user: {
|
user: {
|
||||||
@ -221,4 +221,30 @@ module("Unit | Model | user", function (hooks) {
|
|||||||
await user.hideUserTipForever("first_notification");
|
await user.hideUserTipForever("first_notification");
|
||||||
assert.strictEqual(requestsCount, 1);
|
assert.strictEqual(requestsCount, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("hideUserTipForever() can hide the user tip", async function (assert) {
|
||||||
|
const site = getOwner(this).lookup("service:site");
|
||||||
|
site.set("user_tips", { first_notification: 1 });
|
||||||
|
const store = getOwner(this).lookup("service:store");
|
||||||
|
const user = store.createRecord("user", { username: "eviltrout" });
|
||||||
|
|
||||||
|
const hideSpy = sinon.spy(userTips, "hideUserTip");
|
||||||
|
const showNextSpy = sinon.spy(userTips, "showNextUserTip");
|
||||||
|
await user.hideUserTipForever("first_notification");
|
||||||
|
|
||||||
|
assert.ok(hideSpy.calledWith("first_notification"));
|
||||||
|
assert.ok(showNextSpy.calledWith());
|
||||||
|
});
|
||||||
|
|
||||||
|
test("hideUserTipForever() can hide all the user tips", async function (assert) {
|
||||||
|
const site = getOwner(this).lookup("service:site");
|
||||||
|
site.set("user_tips", { first_notification: 1 });
|
||||||
|
const store = getOwner(this).lookup("service:store");
|
||||||
|
const user = store.createRecord("user", { username: "eviltrout" });
|
||||||
|
|
||||||
|
const hideAllSpy = sinon.spy(userTips, "hideAllUserTips");
|
||||||
|
await user.hideUserTipForever();
|
||||||
|
|
||||||
|
assert.ok(hideAllSpy.calledWith());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -248,6 +248,13 @@ class UserUpdater
|
|||||||
user_notification_schedule.create_do_not_disturb_timings(delete_existing: true) :
|
user_notification_schedule.create_do_not_disturb_timings(delete_existing: true) :
|
||||||
user_notification_schedule.destroy_scheduled_timings
|
user_notification_schedule.destroy_scheduled_timings
|
||||||
end
|
end
|
||||||
|
if attributes.key?(:seen_popups) || attributes.key?(:skip_new_user_tips)
|
||||||
|
MessageBus.publish(
|
||||||
|
'/user-tips',
|
||||||
|
user.user_option.seen_popups,
|
||||||
|
user_ids: [user.id]
|
||||||
|
)
|
||||||
|
end
|
||||||
DiscourseEvent.trigger(:user_updated, user)
|
DiscourseEvent.trigger(:user_updated, user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -526,16 +526,33 @@ RSpec.describe UserUpdater do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'when skip_new_user_tips is edited' do
|
context 'when skip_new_user_tips is edited' do
|
||||||
it 'updates all fields' do
|
it 'updates seen_popups too' do
|
||||||
UserUpdater.new(Discourse.system_user, user).update(skip_new_user_tips: true)
|
messages = MessageBus.track_publish('/user-tips') do
|
||||||
|
UserUpdater.new(Discourse.system_user, user).update(skip_new_user_tips: true)
|
||||||
|
end
|
||||||
|
|
||||||
expect(user.user_option.skip_new_user_tips).to eq(true)
|
expect(user.user_option.skip_new_user_tips).to eq(true)
|
||||||
expect(user.user_option.seen_popups).to eq([-1])
|
expect(user.user_option.seen_popups).to eq([-1])
|
||||||
|
expect(messages.map(&:data)).to contain_exactly([-1])
|
||||||
|
|
||||||
UserUpdater.new(Discourse.system_user, user).update(skip_new_user_tips: false)
|
messages = MessageBus.track_publish('/user-tips') do
|
||||||
|
UserUpdater.new(Discourse.system_user, user).update(skip_new_user_tips: false)
|
||||||
|
end
|
||||||
|
|
||||||
expect(user.user_option.skip_new_user_tips).to eq(false)
|
expect(user.user_option.skip_new_user_tips).to eq(false)
|
||||||
expect(user.user_option.seen_popups).to eq(nil)
|
expect(user.user_option.seen_popups).to eq(nil)
|
||||||
|
expect(messages.map(&:data)).to contain_exactly(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when seen_popups is edited' do
|
||||||
|
it 'publishes a message' do
|
||||||
|
messages = MessageBus.track_publish('/user-tips') do
|
||||||
|
UserUpdater.new(Discourse.system_user, user).update(seen_popups: [1])
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(user.user_option.seen_popups).to eq([1])
|
||||||
|
expect(messages.map(&:data)).to contain_exactly([1])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user