DEV: Convert User model to native class syntax (#25628)

This commit was created with a combination of the ember-native-class-codemod and manual cleanup.

User-status-related functionality was previously encapsulated in its own `User.reopen` call, which is essentially an 'inline mixin'. This commit refactors it into a utility class, with an instance accessible on `User#statusManager`
This commit is contained in:
David Taylor 2024-02-13 10:49:18 +00:00 committed by GitHub
parent 9883e6a0c8
commit 061e79297f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 221 additions and 209 deletions

View File

@ -207,7 +207,7 @@ export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, {
);
}
this.setProperties({ user });
this.user.trackStatus();
this.user.statusManager.trackStatus();
return user;
})
.catch(() => this._close())
@ -216,7 +216,7 @@ export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, {
_close() {
if (this.user) {
this.user.stopTrackingStatus();
this.user.statusManager.stopTrackingStatus();
}
this.setProperties({

View File

@ -14,12 +14,12 @@ export default Component.extend({
didInsertElement() {
this._super(...arguments);
this.user?.trackStatus?.();
this.user?.statusManager?.trackStatus();
},
willDestroyElement() {
this._super(...arguments);
this.user?.stopTrackingStatus?.();
this.user?.statusManager?.stopTrackingStatus();
},
@discourseComputed("user.username")

View File

@ -1,3 +1,4 @@
import { getOwner, setOwner } from "@ember/application";
import { A } from "@ember/array";
import EmberObject, { computed, get, getProperties } from "@ember/object";
import { dependentKeyCompat } from "@ember/object/compat";
@ -169,74 +170,83 @@ function userOption(userOptionKey) {
});
}
const User = RestModel.extend({
appEvents: service(),
userTips: service(),
export default class User extends RestModel.extend(Evented) {
@service appEvents;
@service userTips;
mailing_list_mode: userOption("mailing_list_mode"),
external_links_in_new_tab: userOption("external_links_in_new_tab"),
enable_quoting: userOption("enable_quoting"),
dynamic_favicon: userOption("dynamic_favicon"),
automatically_unpin_topics: userOption("automatically_unpin_topics"),
likes_notifications_disabled: userOption("likes_notifications_disabled"),
hide_profile_and_presence: userOption("hide_profile_and_presence"),
title_count_mode: userOption("title_count_mode"),
enable_defer: userOption("enable_defer"),
timezone: userOption("timezone"),
skip_new_user_tips: userOption("skip_new_user_tips"),
default_calendar: userOption("default_calendar"),
bookmark_auto_delete_preference: userOption(
"bookmark_auto_delete_preference"
),
seen_popups: userOption("seen_popups"),
should_be_redirected_to_top: userOption("should_be_redirected_to_top"),
redirected_to_top: userOption("redirected_to_top"),
treat_as_new_topic_start_date: userOption("treat_as_new_topic_start_date"),
@userOption("mailing_list_mode") mailing_list_mode;
@userOption("external_links_in_new_tab") external_links_in_new_tab;
@userOption("enable_quoting") enable_quoting;
@userOption("dynamic_favicon") dynamic_favicon;
@userOption("automatically_unpin_topics") automatically_unpin_topics;
@userOption("likes_notifications_disabled") likes_notifications_disabled;
@userOption("hide_profile_and_presence") hide_profile_and_presence;
@userOption("title_count_mode") title_count_mode;
@userOption("enable_defer") enable_defer;
@userOption("timezone") timezone;
@userOption("skip_new_user_tips") skip_new_user_tips;
@userOption("default_calendar") default_calendar;
@userOption("bookmark_auto_delete_preference")
bookmark_auto_delete_preference;
@userOption("seen_popups") seen_popups;
@userOption("should_be_redirected_to_top") should_be_redirected_to_top;
@userOption("redirected_to_top") redirected_to_top;
@userOption("treat_as_new_topic_start_date") treat_as_new_topic_start_date;
hasPMs: gt("private_messages_stats.all", 0),
hasStartedPMs: gt("private_messages_stats.mine", 0),
hasUnreadPMs: gt("private_messages_stats.unread", 0),
@gt("private_messages_stats.all", 0) hasPMs;
@gt("private_messages_stats.mine", 0) hasStartedPMs;
@gt("private_messages_stats.unread", 0) hasUnreadPMs;
@url("id", "username_lower", "/admin/users/%@1/%@2") adminPath;
@equal("trust_level", 0) isBasic;
@equal("trust_level", 3) isRegular;
@equal("trust_level", 4) isLeader;
@or("staff", "isLeader") canManageTopic;
@alias("sidebar_category_ids") sidebarCategoryIds;
@alias("sidebar_sections") sidebarSections;
@mapBy("sidebarTags", "name") sidebarTagNames;
@filterBy("groups", "has_messages", true) groupsWithMessages;
numGroupsToDisplay = 2;
statusManager = new UserStatusManager(this);
@discourseComputed("can_be_deleted", "post_count")
canBeDeleted(canBeDeleted, postCount) {
const maxPostCount = this.siteSettings.delete_all_posts_max;
return canBeDeleted && postCount <= maxPostCount;
},
}
@discourseComputed()
stream() {
return UserStream.create({ user: this });
},
}
@discourseComputed()
bookmarks() {
return Bookmark.create({ user: this });
},
}
@discourseComputed()
postsStream() {
return UserPostsStream.create({ user: this });
},
}
@discourseComputed()
userDraftsStream() {
return UserDraftsStream.create({ user: this });
},
}
staff: computed("admin", "moderator", {
get() {
@computed("admin", "moderator")
get staff() {
return this.admin || this.moderator;
},
}
// prevents staff property to be overridden
set() {
return this.admin || this.moderator;
},
}),
set staff(value) {}
destroySession() {
return ajax(`/session/${this.username}`, { type: "DELETE" });
},
}
@discourseComputed("username_lower")
searchContext(username) {
@ -245,7 +255,7 @@ const User = RestModel.extend({
id: username,
user: this,
};
},
}
@discourseComputed("username", "name")
displayName(username, name) {
@ -253,7 +263,7 @@ const User = RestModel.extend({
return name;
}
return username;
},
}
@discourseComputed("profile_background_upload_url")
profileBackgroundUrl(bgUrl) {
@ -261,13 +271,13 @@ const User = RestModel.extend({
return htmlSafe("");
}
return htmlSafe("background-image: url(" + getURLWithCDN(bgUrl) + ")");
},
}
@discourseComputed()
path() {
// no need to observe, requires a hard refresh to update
return userPath(this.username_lower);
},
}
@discourseComputed()
userApiKeys() {
@ -287,7 +297,7 @@ const User = RestModel.extend({
return obj;
});
}
},
}
revokeApiKey(key) {
return ajax("/user-api-key/revoke", {
@ -296,7 +306,7 @@ const User = RestModel.extend({
}).then(() => {
key.set("revoked", true);
});
},
}
undoRevokeApiKey(key) {
return ajax("/user-api-key/undo-revoke", {
@ -305,7 +315,7 @@ const User = RestModel.extend({
}).then(() => {
key.set("revoked", false);
});
},
}
pmPath(topic) {
const userId = this.id;
@ -323,35 +333,33 @@ const User = RestModel.extend({
return userPath(`${username}/messages/group/${groups[0].name}`);
}
}
},
adminPath: url("id", "username_lower", "/admin/users/%@1/%@2"),
}
@discourseComputed()
mutedTopicsPath() {
return defaultHomepage() === "latest"
? getURL("/?state=muted")
: getURL("/latest?state=muted");
},
}
@discourseComputed()
watchingTopicsPath() {
return defaultHomepage() === "latest"
? getURL("/?state=watching")
: getURL("/latest?state=watching");
},
}
@discourseComputed()
trackingTopicsPath() {
return defaultHomepage() === "latest"
? getURL("/?state=tracking")
: getURL("/latest?state=tracking");
},
}
@discourseComputed("username")
username_lower(username) {
return username.toLowerCase();
},
}
@discourseComputed("trust_level")
trustLevel(trustLevel) {
@ -359,36 +367,37 @@ const User = RestModel.extend({
"id",
parseInt(trustLevel, 10)
);
},
isBasic: equal("trust_level", 0),
isRegular: equal("trust_level", 3),
isLeader: equal("trust_level", 4),
canManageTopic: or("staff", "isLeader"),
}
@discourseComputed("previous_visit_at")
previousVisitAt(previous_visit_at) {
return new Date(previous_visit_at);
},
}
@discourseComputed("suspended_till")
suspended(suspendedTill) {
return suspendedTill && moment(suspendedTill).isAfter();
},
}
@discourseComputed("suspended_till")
suspendedForever: isForever,
suspendedForever(suspendedTill) {
return isForever(suspendedTill);
}
@discourseComputed("silenced_till")
silencedForever: isForever,
silencedForever(silencedTill) {
isForever(silencedTill);
}
@discourseComputed("suspended_till")
suspendedTillDate: longDate,
suspendedTillDate(silencedTill) {
return longDate(silencedTill);
}
@discourseComputed("silenced_till")
silencedTillDate: longDate,
sidebarCategoryIds: alias("sidebar_category_ids"),
silencedTillDate(silencedTill) {
return longDate(silencedTill);
}
@discourseComputed("sidebar_tags.[]")
sidebarTags(sidebarTags) {
@ -399,18 +408,14 @@ const User = RestModel.extend({
return sidebarTags.sort((a, b) => {
return a.name.localeCompare(b.name);
});
},
sidebarSections: alias("sidebar_sections"),
sidebarTagNames: mapBy("sidebarTags", "name"),
}
changeUsername(new_username) {
return ajax(userPath(`${this.username_lower}/preferences/username`), {
type: "PUT",
data: { new_username },
});
},
}
addEmail(email) {
return ajax(userPath(`${this.username_lower}/preferences/email`), {
@ -423,7 +428,7 @@ const User = RestModel.extend({
this.unconfirmed_emails.pushObject(email);
});
},
}
changeEmail(email) {
return ajax(userPath(`${this.username_lower}/preferences/email`), {
@ -436,7 +441,7 @@ const User = RestModel.extend({
this.unconfirmed_emails.pushObject(email);
});
},
}
save(fields) {
const data = this.getProperties(
@ -506,7 +511,7 @@ const User = RestModel.extend({
.finally(() => {
this.set("isSaving", false);
});
},
}
setPrimaryEmail(email) {
return ajax(userPath(`${this.username}/preferences/primary-email.json`), {
@ -517,7 +522,7 @@ const User = RestModel.extend({
this.secondary_emails.pushObject(this.email);
this.set("email", email);
});
},
}
destroyEmail(email) {
return ajax(userPath(`${this.username}/preferences/email.json`), {
@ -530,7 +535,7 @@ const User = RestModel.extend({
this.secondary_emails.removeObject(email);
}
});
},
}
changePassword() {
return ajax("/session/forgot_password", {
@ -538,55 +543,55 @@ const User = RestModel.extend({
data: { login: this.email || this.username },
type: "POST",
});
},
}
loadSecondFactorCodes() {
return ajax("/u/second_factors.json", {
type: "POST",
});
},
}
requestSecurityKeyChallenge() {
return ajax("/u/create_second_factor_security_key.json", {
type: "POST",
});
},
}
registerSecurityKey(credential) {
return ajax("/u/register_second_factor_security_key.json", {
data: credential,
type: "POST",
});
},
}
trustedSession() {
return ajax("/u/trusted-session.json");
},
}
createPasskey() {
return ajax("/u/create_passkey.json", {
type: "POST",
});
},
}
registerPasskey(credential) {
return ajax("/u/register_passkey.json", {
data: credential,
type: "POST",
});
},
}
deletePasskey(id) {
return ajax(`/u/delete_passkey/${id}`, {
type: "DELETE",
});
},
}
createSecondFactorTotp() {
return ajax("/u/create_second_factor_totp.json", {
type: "POST",
});
},
}
enableSecondFactorTotp(authToken, name) {
return ajax("/u/enable_second_factor_totp.json", {
@ -596,13 +601,13 @@ const User = RestModel.extend({
},
type: "POST",
});
},
}
disableAllSecondFactors() {
return ajax("/u/disable_second_factor.json", {
type: "PUT",
});
},
}
updateSecondFactor(id, name, disable, targetMethod) {
return ajax("/u/second_factor.json", {
@ -614,7 +619,7 @@ const User = RestModel.extend({
},
type: "PUT",
});
},
}
updateSecurityKey(id, name, disable) {
return ajax("/u/security_key.json", {
@ -625,7 +630,7 @@ const User = RestModel.extend({
},
type: "PUT",
});
},
}
toggleSecondFactor(authToken, authMethod, targetMethod, enable) {
return ajax("/u/second_factor.json", {
@ -637,20 +642,20 @@ const User = RestModel.extend({
},
type: "PUT",
});
},
}
generateSecondFactorCodes() {
return ajax("/u/second_factors_backup.json", {
type: "PUT",
});
},
}
revokeAssociatedAccount(providerName) {
return ajax(userPath(`${this.username}/preferences/revoke-account`), {
data: { provider_name: providerName },
type: "POST",
});
},
}
async loadUserAction(id) {
const result = await ajax(`/user_actions/${id}.json`);
@ -673,16 +678,14 @@ const User = RestModel.extend({
const action = UserAction.collapseStream([UserAction.create(ua)]);
this.stream.set("itemsLoaded", this.stream.get("itemsLoaded") + 1);
this.stream.get("content").insertAt(0, action[0]);
},
}
inAllStream(ua) {
return (
ua.action_type === UserAction.TYPES.posts ||
ua.action_type === UserAction.TYPES.topics
);
},
numGroupsToDisplay: 2,
}
@discourseComputed("groups.[]")
filteredGroups() {
@ -691,15 +694,13 @@ const User = RestModel.extend({
return groups.filter((group) => {
return !group.automatic || group.name === "moderators";
});
},
groupsWithMessages: filterBy("groups", "has_messages", true),
}
@discourseComputed("filteredGroups", "numGroupsToDisplay")
displayGroups(filteredGroups, numGroupsToDisplay) {
const groups = filteredGroups.slice(0, numGroupsToDisplay);
return groups.length === 0 ? null : groups;
},
}
// NOTE: This only includes groups *visible* to the user via the serializer,
// so be wary when using this.
@ -713,7 +714,7 @@ const User = RestModel.extend({
groupIds.includes(0) ||
this.groups.mapBy("id").some((groupId) => groupIds.includes(groupId))
);
},
}
// The user's stat count, excluding PMs.
@discourseComputed("statsExcludingPms.@each.count")
@ -728,7 +729,7 @@ const User = RestModel.extend({
}
});
return count;
},
}
// The user's stats, excluding PMs.
@discourseComputed("stats.@each.isPM")
@ -737,7 +738,7 @@ const User = RestModel.extend({
return [];
}
return this.stats.rejectBy("isPM");
},
}
findDetails(options) {
const user = this;
@ -803,7 +804,7 @@ const User = RestModel.extend({
user.setProperties(json.user);
return user;
});
},
}
findStaffInfo() {
if (!User.currentProp("staff")) {
@ -814,21 +815,21 @@ const User = RestModel.extend({
this.setProperties(info);
}
);
},
}
pickAvatar(upload_id, type) {
return ajax(userPath(`${this.username_lower}/preferences/avatar/pick`), {
type: "PUT",
data: { upload_id, type },
});
},
}
selectAvatar(avatarUrl) {
return ajax(userPath(`${this.username_lower}/preferences/avatar/select`), {
type: "PUT",
data: { url: avatarUrl },
});
},
}
isAllowedToUploadAFile(type) {
const settingName = type === "image" ? "embedded_media" : "attachments";
@ -838,21 +839,21 @@ const User = RestModel.extend({
this.trust_level > 0 ||
this.siteSettings[`newuser_max_${settingName}`] > 0
);
},
}
createInvite(email, group_ids, custom_message) {
return ajax("/invites", {
type: "POST",
data: { email, group_ids, custom_message },
});
},
}
generateInviteLink(email, group_ids, topic_id) {
return ajax("/invites", {
type: "POST",
data: { email, skip_email: true, group_ids, topic_id },
});
},
}
@dependentKeyCompat
get mutedCategories() {
@ -866,13 +867,14 @@ const User = RestModel.extend({
}
return Category.findByIds(this.get("muted_category_ids"));
},
}
set mutedCategories(categories) {
this.set(
"muted_category_ids",
categories.map((c) => c.id)
);
},
}
@dependentKeyCompat
get regularCategories() {
@ -886,13 +888,14 @@ const User = RestModel.extend({
}
return Category.findByIds(this.get("regular_category_ids"));
},
}
set regularCategories(categories) {
this.set(
"regular_category_ids",
categories.map((c) => c.id)
);
},
}
@dependentKeyCompat
get trackedCategories() {
@ -906,13 +909,14 @@ const User = RestModel.extend({
}
return Category.findByIds(this.get("tracked_category_ids"));
},
}
set trackedCategories(categories) {
this.set(
"tracked_category_ids",
categories.map((c) => c.id)
);
},
}
@dependentKeyCompat
get watchedCategories() {
@ -926,13 +930,14 @@ const User = RestModel.extend({
}
return Category.findByIds(this.get("watched_category_ids"));
},
}
set watchedCategories(categories) {
this.set(
"watched_category_ids",
categories.map((c) => c.id)
);
},
}
@dependentKeyCompat
get watchedFirstPostCategories() {
@ -946,28 +951,29 @@ const User = RestModel.extend({
}
return Category.findByIds(this.get("watched_first_post_category_ids"));
},
}
set watchedFirstPostCategories(categories) {
this.set(
"watched_first_post_category_ids",
categories.map((c) => c.id)
);
},
}
@discourseComputed("can_delete_account")
canDeleteAccount(canDeleteAccount) {
return !this.siteSettings.enable_discourse_connect && canDeleteAccount;
},
}
@dependentKeyCompat
get sidebarLinkToFilteredList() {
return this.get("user_option.sidebar_link_to_filtered_list");
},
}
@dependentKeyCompat
get sidebarShowCountOfNewItems() {
return this.get("user_option.sidebar_show_count_of_new_items");
},
}
delete() {
if (this.can_delete_account) {
@ -978,7 +984,7 @@ const User = RestModel.extend({
} else {
return Promise.reject(I18n.t("user.delete_yourself_not_allowed"));
}
},
}
updateNotificationLevel({ level, expiringAt = null, actingUser = null }) {
if (!actingUser) {
@ -1001,7 +1007,7 @@ const User = RestModel.extend({
actingUser.ignored_users.addObject(this.username);
}
});
},
}
dismissBanner(bannerKey) {
this.set("dismissed_banner_key", bannerKey);
@ -1009,7 +1015,7 @@ const User = RestModel.extend({
type: "PUT",
data: { dismissed_banner_key: bannerKey },
});
},
}
checkEmail() {
return ajax(userPath(`${this.username_lower}/emails.json`), {
@ -1024,7 +1030,7 @@ const User = RestModel.extend({
});
}
});
},
}
summary() {
const store = getOwnerWithFallback(this).lookup("service:store");
@ -1072,13 +1078,13 @@ const User = RestModel.extend({
return summary;
}
);
},
}
canManageGroup(group) {
return group.get("automatic")
? false
: group.get("can_admin_group") || group.get("is_group_owner");
},
}
@discourseComputed("groups.@each.title", "badges.[]")
availableTitles() {
@ -1105,7 +1111,7 @@ const User = RestModel.extend({
id: title,
};
});
},
}
@discourseComputed("groups.[]")
availableFlairs() {
@ -1126,7 +1132,7 @@ const User = RestModel.extend({
}
return flairs;
},
}
@discourseComputed("user_option.text_size_seq", "user_option.text_size")
currentTextSize(serverSeq, serverSize) {
@ -1137,7 +1143,7 @@ const User = RestModel.extend({
}
}
return serverSize;
},
}
updateTextSizeCookie(newSize) {
if (newSize) {
@ -1149,7 +1155,7 @@ const User = RestModel.extend({
} else {
removeCookie(TEXT_SIZE_COOKIE_NAME, { path: "/" });
}
},
}
@discourseComputed("second_factor_enabled", "staff")
enforcedSecondFactor(secondFactorEnabled, staff) {
@ -1158,7 +1164,7 @@ const User = RestModel.extend({
!secondFactorEnabled &&
(enforce === "all" || (enforce === "staff" && staff))
);
},
}
resolvedTimezone() {
deprecated(
@ -1171,7 +1177,7 @@ const User = RestModel.extend({
);
return this.user_option.timezone;
},
}
calculateMutedIds(notificationLevel, id, type) {
const muted_ids = this.get(type);
@ -1180,14 +1186,14 @@ const User = RestModel.extend({
} else {
return muted_ids.filter((existing_id) => existing_id !== id);
}
},
}
setPrimaryGroup(primaryGroupId) {
return ajax(`/admin/users/${this.id}/primary_group`, {
type: "PUT",
data: { primary_group_id: primaryGroupId },
});
},
}
enterDoNotDisturbFor(duration) {
return ajax({
@ -1197,7 +1203,7 @@ const User = RestModel.extend({
}).then((response) => {
return this.updateDoNotDisturbStatus(response.ends_at);
});
},
}
leaveDoNotDisturb() {
return ajax({
@ -1206,29 +1212,29 @@ const User = RestModel.extend({
}).then(() => {
this.updateDoNotDisturbStatus(null);
});
},
}
updateDoNotDisturbStatus(ends_at) {
this.set("do_not_disturb_until", ends_at);
this.appEvents.trigger("do-not-disturb:changed", this.do_not_disturb_until);
},
}
updateDraftProperties(properties) {
this.setProperties(properties);
this.appEvents.trigger("user-drafts:changed");
},
}
updateReviewableCount(count) {
this.set("reviewable_count", count);
this.appEvents.trigger("user-reviewable-count:changed", count);
},
}
isInDoNotDisturb() {
return (
this.do_not_disturb_until &&
new Date(this.do_not_disturb_until) >= new Date()
);
},
}
@discourseComputed(
"tracked_tags.[]",
@ -1237,8 +1243,8 @@ const User = RestModel.extend({
)
trackedTags(trackedTags, watchedTags, watchingFirstPostTags) {
return [...trackedTags, ...watchedTags, ...watchingFirstPostTags];
},
});
}
}
User.reopenClass(Singleton, {
// Find a `User` for a given username.
@ -1269,7 +1275,7 @@ User.reopenClass(Singleton, {
const store = getOwnerWithFallback(this).lookup("service:store");
const currentUser = store.createRecord("user", userJson);
currentUser.trackStatus();
currentUser.statusManager.trackStatus();
return currentUser;
}
@ -1379,13 +1385,21 @@ User.reopenClass(Singleton, {
});
// user status tracking
User.reopen(Evented, {
_subscribersCount: 0,
_clearStatusTimerId: null,
class UserStatusManager {
@service appEvents;
user;
_subscribersCount = 0;
_clearStatusTimerId = null;
constructor(user) {
this.user = user;
setOwner(this, getOwner(user));
}
// always call stopTrackingStatus() when done with a user
trackStatus() {
if (!this.id && !isTesting()) {
if (!this.user.id && !isTesting()) {
// eslint-disable-next-line no-console
console.warn(
"It's impossible to track user status on a user model that doesn't have id. This user model won't be receiving live user status updates."
@ -1393,17 +1407,17 @@ User.reopen(Evented, {
}
if (this._subscribersCount === 0) {
this.addObserver("status", this, "_statusChanged");
this.user.addObserver("status", this, "_statusChanged");
this.appEvents.on("user-status:changed", this, this._updateStatus);
if (this.status && this.status.ends_at) {
this._scheduleStatusClearing(this.status.ends_at);
if (this.user.status?.ends_at) {
this._scheduleStatusClearing(this.user.status.ends_at);
}
}
this._subscribersCount++;
},
}
stopTrackingStatus() {
if (this._subscribersCount === 0) {
@ -1412,28 +1426,28 @@ User.reopen(Evented, {
if (this._subscribersCount === 1) {
// the last subscriber is unsubscribing
this.removeObserver("status", this, "_statusChanged");
this.user.removeObserver("status", this, "_statusChanged");
this.appEvents.off("user-status:changed", this, this._updateStatus);
this._unscheduleStatusClearing();
}
this._subscribersCount--;
},
}
isTrackingStatus() {
return this._subscribersCount > 0;
},
}
_statusChanged(sender, key) {
this.trigger("status-changed");
_statusChanged() {
this.user.trigger("status-changed");
const status = this.get(key);
const status = this.user.status;
if (status && status.ends_at) {
this._scheduleStatusClearing(status.ends_at);
} else {
this._unscheduleStatusClearing();
}
},
}
_scheduleStatusClearing(endsAt) {
if (isTesting()) {
@ -1451,23 +1465,23 @@ User.reopen(Evented, {
"_autoClearStatus",
remaining
);
},
}
_unscheduleStatusClearing() {
cancel(this._clearStatusTimerId);
this._clearStatusTimerId = null;
},
}
_autoClearStatus() {
this.set("status", null);
},
this.user.set("status", null);
}
_updateStatus(statuses) {
if (statuses.hasOwnProperty(this.id)) {
this.set("status", statuses[this.id]);
if (statuses.hasOwnProperty(this.user.id)) {
this.user.set("status", statuses[this.user.id]);
}
}
}
},
});
if (typeof Discourse !== "undefined") {
let warned = false;
@ -1485,5 +1499,3 @@ if (typeof Discourse !== "undefined") {
},
});
}
export default User;

View File

@ -36,7 +36,7 @@ export default DiscourseRoute.extend({
return user
.findDetails()
.then(() => user.findStaffInfo())
.then(() => user.trackStatus())
.then(() => user.statusManager.trackStatus())
.catch(() => this.router.replaceWith("/404"));
},
@ -76,7 +76,7 @@ export default DiscourseRoute.extend({
`/u/${user.username_lower}/counters`,
this.onUserCountersMessage
);
user.stopTrackingStatus();
user.statusManager.stopTrackingStatus();
// Remove the search context
this.searchService.searchContext = null;

View File

@ -407,14 +407,14 @@ export default class PostCooked {
_trackMentionedUsersStatus() {
this._post()?.mentioned_users?.forEach((user) => {
user.trackStatus?.();
user.statusManager?.trackStatus?.();
user.on?.("status-changed", this, "_rerenderUserStatusOnMentions");
});
}
_stopTrackingMentionedUsersStatus() {
this._post()?.mentioned_users?.forEach((user) => {
user.stopTrackingStatus?.();
user.statusManager?.stopTrackingStatus?.();
user.off?.("status-changed", this, "_rerenderUserStatusOnMentions");
});
}

View File

@ -61,7 +61,7 @@ export default createWidget("poster-name", {
didRenderWidget() {
if (this.attrs.user) {
this.attrs.user.trackStatus();
this.attrs.user.statusManager.trackStatus();
this.attrs.user.on("status-changed", this, "scheduleRerender");
}
},
@ -69,7 +69,7 @@ export default createWidget("poster-name", {
willRerenderWidget() {
if (this.attrs.user) {
this.attrs.user.off("status-changed", this, "scheduleRerender");
this.attrs.user.stopTrackingStatus();
this.attrs.user.statusManager.stopTrackingStatus();
}
},

View File

@ -344,7 +344,7 @@ export function acceptance(name, optionsOrCallback) {
updateCurrentUser(userChanges);
}
User.current().trackStatus();
User.current().statusManager.trackStatus();
}
if (settingChanges) {
@ -372,7 +372,7 @@ export function acceptance(name, optionsOrCallback) {
let app = getApplication();
options?.afterEach?.call(this);
if (loggedIn) {
User.current().stopTrackingStatus();
User.current().statusManager.stopTrackingStatus();
}
testCleanup(this.container, app);

View File

@ -120,25 +120,25 @@ module("Unit | Model | user", function (hooks) {
test("subsequent calls to trackStatus and stopTrackingStatus increase and decrease subscribers counter", function (assert) {
const store = getOwner(this).lookup("service:store");
const user = store.createRecord("user");
assert.strictEqual(user._subscribersCount, 0);
assert.strictEqual(user.statusManager._subscribersCount, 0);
user.trackStatus();
assert.strictEqual(user._subscribersCount, 1);
user.statusManager.trackStatus();
assert.strictEqual(user.statusManager._subscribersCount, 1);
user.trackStatus();
assert.strictEqual(user._subscribersCount, 2);
user.statusManager.trackStatus();
assert.strictEqual(user.statusManager._subscribersCount, 2);
user.stopTrackingStatus();
assert.strictEqual(user._subscribersCount, 1);
user.statusManager.stopTrackingStatus();
assert.strictEqual(user.statusManager._subscribersCount, 1);
user.stopTrackingStatus();
assert.strictEqual(user._subscribersCount, 0);
user.statusManager.stopTrackingStatus();
assert.strictEqual(user.statusManager._subscribersCount, 0);
});
test("attempt to stop tracking status if status wasn't tracked doesn't throw", function (assert) {
const store = getOwner(this).lookup("service:store");
const user = store.createRecord("user");
user.stopTrackingStatus();
user.statusManager.stopTrackingStatus();
assert.ok(true);
});
@ -160,8 +160,8 @@ module("Unit | Model | user", function (hooks) {
const appEvents = user1.appEvents;
try {
user1.trackStatus();
user2.trackStatus();
user1.statusManager.trackStatus();
user2.statusManager.trackStatus();
assert.strictEqual(user1.status, status1);
assert.strictEqual(user2.status, status2);
@ -173,8 +173,8 @@ module("Unit | Model | user", function (hooks) {
assert.strictEqual(user1.status, null);
assert.strictEqual(user2.status, null);
} finally {
user1.stopTrackingStatus();
user2.stopTrackingStatus();
user1.statusManager.stopTrackingStatus();
user2.statusManager.stopTrackingStatus();
}
});

View File

@ -158,12 +158,12 @@ export default class ChatChannelRow extends Component {
@action
startTrackingStatus() {
this.#firstDirectMessageUser?.trackStatus();
this.#firstDirectMessageUser?.statusManager.trackStatus();
}
@action
stopTrackingStatus() {
this.#firstDirectMessageUser?.stopTrackingStatus();
this.#firstDirectMessageUser?.statusManager.stopTrackingStatus();
}
<template>

View File

@ -249,11 +249,11 @@ export default class ChatMessage extends Component {
@action
initMentionedUsers() {
this.args.message.mentionedUsers.forEach((user) => {
if (user.isTrackingStatus()) {
if (user.statusManager.isTrackingStatus()) {
return;
}
user.trackStatus();
user.statusManager.trackStatus();
user.on("status-changed", this, "refreshStatusOnMentions");
});
}
@ -486,7 +486,7 @@ export default class ChatMessage extends Component {
#teardownMentionedUsers() {
this.args.message.mentionedUsers.forEach((user) => {
user.stopTrackingStatus();
user.statusManager.stopTrackingStatus();
user.off("status-changed", this, "refreshStatusOnMentions");
});
}

View File

@ -20,12 +20,12 @@ export default class ChatMessageInfo extends Component {
@bind
trackStatus() {
this.#user?.trackStatus?.();
this.#user?.statusManager.trackStatus();
}
@bind
stopTrackingStatus() {
this.#user?.stopTrackingStatus?.();
this.#user?.statusManager.stopTrackingStatus();
}
get usernameClasses() {

View File

@ -292,7 +292,7 @@ export default {
if (this.oneOnOneMessage) {
const user = this.channel.chatable.users[0];
if (user.username !== I18n.t("chat.deleted_chat_username")) {
user.trackStatus();
user.statusManager.trackStatus();
}
}
}
@ -300,7 +300,7 @@ export default {
@bind
willDestroy() {
if (this.oneOnOneMessage) {
this.channel.chatable.users[0].stopTrackingStatus();
this.channel.chatable.users[0].statusManager.stopTrackingStatus();
}
}