diff --git a/app/assets/javascripts/admin/addon/routes/admin-customize-themes-show.js b/app/assets/javascripts/admin/addon/routes/admin-customize-themes-show.js
index 156dbf9dd0c..a3d31c1bbcd 100644
--- a/app/assets/javascripts/admin/addon/routes/admin-customize-themes-show.js
+++ b/app/assets/javascripts/admin/addon/routes/admin-customize-themes-show.js
@@ -31,7 +31,7 @@ export default Route.extend({
model,
parentController,
allThemes: parentController.get("model"),
- colorSchemeId: model.get("color_scheme_id"),
+ colorSchemeId: model.get("user_option.color_scheme_id"),
colorSchemes: parentController.get("model.extras.color_schemes"),
editingName: false,
});
diff --git a/app/assets/javascripts/discourse/app/components/bookmark-icon.js b/app/assets/javascripts/discourse/app/components/bookmark-icon.js
index ca18e28607f..3855b471a2c 100644
--- a/app/assets/javascripts/discourse/app/components/bookmark-icon.js
+++ b/app/assets/javascripts/discourse/app/components/bookmark-icon.js
@@ -41,7 +41,7 @@ export default class BookmarkIcon extends Component {
if (!isEmpty(this.bookmark.reminder_at)) {
const formattedTime = formattedReminderTime(
this.bookmark.reminder_at,
- this.currentUser.timezone
+ this.currentUser.user_option.timezone
);
return I18n.t("bookmarks.created_with_reminder_generic", {
date: formattedTime,
diff --git a/app/assets/javascripts/discourse/app/components/bookmark.js b/app/assets/javascripts/discourse/app/components/bookmark.js
index 879ef027fca..811f33e7934 100644
--- a/app/assets/javascripts/discourse/app/components/bookmark.js
+++ b/app/assets/javascripts/discourse/app/components/bookmark.js
@@ -57,7 +57,7 @@ export default Component.extend({
postDetectedLocalTime: null,
postDetectedLocalTimezone: null,
prefilledDatetime: null,
- userTimezone: this.currentUser.timezone,
+ userTimezone: this.currentUser.user_option.timezone,
showOptions: false,
_itsatrap: new ItsATrap(),
autoDeletePreference: this.model.autoDeletePreference || 0,
@@ -154,7 +154,7 @@ export default Component.extend({
}
this.currentUser.set(
- "bookmark_auto_delete_preference",
+ "user_option.bookmark_auto_delete_preference",
this.autoDeletePreference
);
diff --git a/app/assets/javascripts/discourse/app/components/edit-topic-timer-form.js b/app/assets/javascripts/discourse/app/components/edit-topic-timer-form.js
index f499f6e3f5d..456787d5bae 100644
--- a/app/assets/javascripts/discourse/app/components/edit-topic-timer-form.js
+++ b/app/assets/javascripts/discourse/app/components/edit-topic-timer-form.js
@@ -84,7 +84,7 @@ export default Component.extend({
@discourseComputed()
timeOptions() {
- const timezone = this.currentUser.timezone;
+ const timezone = this.currentUser.user_option.timezone;
const shortcuts = timeShortcuts(timezone);
return [
diff --git a/app/assets/javascripts/discourse/app/components/future-date-input.js b/app/assets/javascripts/discourse/app/components/future-date-input.js
index 70c4a98831b..0c3257410f9 100644
--- a/app/assets/javascripts/discourse/app/components/future-date-input.js
+++ b/app/assets/javascripts/discourse/app/components/future-date-input.js
@@ -28,7 +28,7 @@ export default Component.extend({
init() {
this._super(...arguments);
- this.userTimezone = this.currentUser.timezone;
+ this.userTimezone = this.currentUser.user_option.timezone;
},
didReceiveAttrs() {
diff --git a/app/assets/javascripts/discourse/app/components/quote-button.js b/app/assets/javascripts/discourse/app/components/quote-button.js
index a5066f754a1..3c057ce72f7 100644
--- a/app/assets/javascripts/discourse/app/components/quote-button.js
+++ b/app/assets/javascripts/discourse/app/components/quote-button.js
@@ -424,7 +424,7 @@ export default Component.extend(KeyEnterEscape, {
embedQuoteButton(canCreatePost, canReplyAsNewTopic) {
return (
(canCreatePost || canReplyAsNewTopic) &&
- this.currentUser?.get("enable_quoting")
+ this.currentUser?.get("user_option.enable_quoting")
);
},
diff --git a/app/assets/javascripts/discourse/app/components/time-shortcut-picker.js b/app/assets/javascripts/discourse/app/components/time-shortcut-picker.js
index 26a65a0f1c1..504a6043fdf 100644
--- a/app/assets/javascripts/discourse/app/components/time-shortcut-picker.js
+++ b/app/assets/javascripts/discourse/app/components/time-shortcut-picker.js
@@ -68,7 +68,7 @@ export default Component.extend({
@on("init")
_setupPicker() {
this.setProperties({
- userTimezone: this.currentUser.timezone,
+ userTimezone: this.currentUser.user_option.timezone,
hiddenOptions: this.hiddenOptions || [],
customOptions: this.customOptions || [],
customLabels: this.customLabels || {},
diff --git a/app/assets/javascripts/discourse/app/components/topic-footer-buttons.js b/app/assets/javascripts/discourse/app/components/topic-footer-buttons.js
index 5f91ecca8e2..af67f35d264 100644
--- a/app/assets/javascripts/discourse/app/components/topic-footer-buttons.js
+++ b/app/assets/javascripts/discourse/app/components/topic-footer-buttons.js
@@ -56,7 +56,7 @@ export default Component.extend({
canInviteTo: alias("topic.details.can_invite_to"),
- canDefer: alias("currentUser.enable_defer"),
+ canDefer: alias("currentUser.user_option.enable_defer"),
inviteDisabled: or("topic.archived", "topic.closed", "topic.deleted"),
diff --git a/app/assets/javascripts/discourse/app/components/user-card-contents.js b/app/assets/javascripts/discourse/app/components/user-card-contents.js
index 34e3147745f..884fcf35d37 100644
--- a/app/assets/javascripts/discourse/app/components/user-card-contents.js
+++ b/app/assets/javascripts/discourse/app/components/user-card-contents.js
@@ -92,7 +92,7 @@ export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, {
if (!this.showUserLocalTime) {
return;
}
- return user.timezone;
+ return user.get("user_option.timezone");
},
@discourseComputed("userTimezone")
diff --git a/app/assets/javascripts/discourse/app/components/user-menu/menu.js b/app/assets/javascripts/discourse/app/components/user-menu/menu.js
index 89ff33435ef..fc963747a34 100644
--- a/app/assets/javascripts/discourse/app/components/user-menu/menu.js
+++ b/app/assets/javascripts/discourse/app/components/user-menu/menu.js
@@ -83,7 +83,7 @@ const CORE_TOP_TABS = [
}
get shouldDisplay() {
- return !this.currentUser.likes_notifications_disabled;
+ return !this.currentUser.user_option.likes_notifications_disabled;
}
get count() {
diff --git a/app/assets/javascripts/discourse/app/components/user-status-message.js b/app/assets/javascripts/discourse/app/components/user-status-message.js
index e49deb10572..857cc030399 100644
--- a/app/assets/javascripts/discourse/app/components/user-status-message.js
+++ b/app/assets/javascripts/discourse/app/components/user-status-message.js
@@ -14,7 +14,7 @@ export default class UserStatusMessage extends Component {
return until(
this.status.ends_at,
- this.currentUser.timezone,
+ this.currentUser.user_option.timezone,
this.currentUser.locale
);
}
diff --git a/app/assets/javascripts/discourse/app/controllers/create-invite.js b/app/assets/javascripts/discourse/app/controllers/create-invite.js
index 1492106b869..3f8dbf832ed 100644
--- a/app/assets/javascripts/discourse/app/controllers/create-invite.js
+++ b/app/assets/javascripts/discourse/app/controllers/create-invite.js
@@ -192,7 +192,7 @@ export default Controller.extend(
@discourseComputed
timeShortcuts() {
- const timezone = this.currentUser.timezone;
+ const timezone = this.currentUser.user_option.timezone;
const shortcuts = timeShortcuts(timezone);
return [
shortcuts.laterToday(),
diff --git a/app/assets/javascripts/discourse/app/controllers/discovery/topics.js b/app/assets/javascripts/discourse/app/controllers/discovery/topics.js
index fb0be3912ff..3b95a44dee7 100644
--- a/app/assets/javascripts/discourse/app/controllers/discovery/topics.js
+++ b/app/assets/javascripts/discourse/app/controllers/discovery/topics.js
@@ -22,7 +22,7 @@ const controllerOpts = {
canStar: alias("currentUser.id"),
showTopicPostBadges: not("new"),
- redirectedReason: alias("currentUser.redirected_to_top.reason"),
+ redirectedReason: alias("currentUser.user_option.redirected_to_top.reason"),
expandGloballyPinned: false,
expandAllPinned: false,
diff --git a/app/assets/javascripts/discourse/app/controllers/download-calendar.js b/app/assets/javascripts/discourse/app/controllers/download-calendar.js
index 7cc803a171a..0336f846019 100644
--- a/app/assets/javascripts/discourse/app/controllers/download-calendar.js
+++ b/app/assets/javascripts/discourse/app/controllers/download-calendar.js
@@ -10,10 +10,10 @@ export default Controller.extend(ModalFunctionality, {
@action
downloadCalendar() {
if (this.remember) {
- this.currentUser.setProperties({
- default_calendar: this.selectedCalendar,
- user_option: { default_calendar: this.selectedCalendar },
- });
+ this.currentUser.user_option.set(
+ "default_calendar",
+ this.selectedCalendar
+ );
this.currentUser.save(["default_calendar"]);
}
if (this.selectedCalendar === "ics") {
diff --git a/app/assets/javascripts/discourse/app/controllers/edit-slow-mode.js b/app/assets/javascripts/discourse/app/controllers/edit-slow-mode.js
index f3c70f5b8be..b3da2b873ab 100644
--- a/app/assets/javascripts/discourse/app/controllers/edit-slow-mode.js
+++ b/app/assets/javascripts/discourse/app/controllers/edit-slow-mode.js
@@ -110,7 +110,7 @@ export default Controller.extend(ModalFunctionality, {
@discourseComputed
timeShortcuts() {
- const timezone = this.currentUser.timezone;
+ const timezone = this.currentUser.user_option.timezone;
const shortcuts = timeShortcuts(timezone);
const nextWeek = shortcuts.monday();
diff --git a/app/assets/javascripts/discourse/app/controllers/ignore-duration-with-username.js b/app/assets/javascripts/discourse/app/controllers/ignore-duration-with-username.js
index 8ead0d77e36..89c5250382d 100644
--- a/app/assets/javascripts/discourse/app/controllers/ignore-duration-with-username.js
+++ b/app/assets/javascripts/discourse/app/controllers/ignore-duration-with-username.js
@@ -13,7 +13,7 @@ export default Controller.extend(ModalFunctionality, {
@discourseComputed
timeShortcuts() {
- const timezone = this.currentUser.timezone;
+ const timezone = this.currentUser.user_option.timezone;
const shortcuts = timeShortcuts(timezone);
return [
shortcuts.laterToday(),
diff --git a/app/assets/javascripts/discourse/app/controllers/ignore-duration.js b/app/assets/javascripts/discourse/app/controllers/ignore-duration.js
index 75a7cb32453..6522d58b010 100644
--- a/app/assets/javascripts/discourse/app/controllers/ignore-duration.js
+++ b/app/assets/javascripts/discourse/app/controllers/ignore-duration.js
@@ -11,7 +11,7 @@ export default Controller.extend(ModalFunctionality, {
@discourseComputed
timeShortcuts() {
- const timezone = this.currentUser.timezone;
+ const timezone = this.currentUser.user_option.timezone;
const shortcuts = timeShortcuts(timezone);
return [
shortcuts.laterToday(),
diff --git a/app/assets/javascripts/discourse/app/controllers/preferences/profile.js b/app/assets/javascripts/discourse/app/controllers/preferences/profile.js
index e396e3e4dfa..f5db9651ec2 100644
--- a/app/assets/javascripts/discourse/app/controllers/preferences/profile.js
+++ b/app/assets/javascripts/discourse/app/controllers/preferences/profile.js
@@ -51,7 +51,7 @@ export default Controller.extend({
});
},
- @discourseComputed("model.default_calendar")
+ @discourseComputed("model.user_option.default_calendar")
canChangeDefaultCalendar(defaultCalendar) {
return defaultCalendar !== "none_selected";
},
@@ -125,12 +125,6 @@ export default Controller.extend({
return model
.save(this.saveAttrNames)
.then(() => {
- // update the timezone in memory so we can use the new
- // one if we change routes without reloading the user
- if (this.currentUser.id === this.model.id) {
- this.currentUser.timezone = this.model.user_option.timezone;
- }
-
cookAsync(model.get("bio_raw"))
.then(() => {
model.set("bio_cooked");
diff --git a/app/assets/javascripts/discourse/app/controllers/topic-bulk-actions.js b/app/assets/javascripts/discourse/app/controllers/topic-bulk-actions.js
index cd5d2cef032..9bbc1558904 100644
--- a/app/assets/javascripts/discourse/app/controllers/topic-bulk-actions.js
+++ b/app/assets/javascripts/discourse/app/controllers/topic-bulk-actions.js
@@ -62,7 +62,7 @@ addBulkButton("deletePostTiming", "defer", {
icon: "circle",
class: "btn-default",
buttonVisible() {
- return this.currentUser.enable_defer;
+ return this.currentUser.user_option.enable_defer;
},
});
addBulkButton("unlistTopics", "unlist_topics", {
diff --git a/app/assets/javascripts/discourse/app/controllers/topic.js b/app/assets/javascripts/discourse/app/controllers/topic.js
index eca4aca13dd..7c27241370b 100644
--- a/app/assets/javascripts/discourse/app/controllers/topic.js
+++ b/app/assets/javascripts/discourse/app/controllers/topic.js
@@ -837,7 +837,7 @@ export default Controller.extend(bufferedProperty("model"), {
bookmarkable_id: post.id,
bookmarkable_type: "Post",
auto_delete_preference:
- this.currentUser.bookmark_auto_delete_preference,
+ this.currentUser.user_option.bookmark_auto_delete_preference,
}),
post
);
@@ -1350,7 +1350,7 @@ export default Controller.extend(bufferedProperty("model"), {
bookmarkable_id: this.model.id,
bookmarkable_type: "Topic",
auto_delete_preference:
- this.currentUser.bookmark_auto_delete_preference,
+ this.currentUser.user_option.bookmark_auto_delete_preference,
})
);
}
@@ -1781,7 +1781,7 @@ export default Controller.extend(bufferedProperty("model"), {
if (
this.siteSettings.automatically_unpin_topics &&
this.currentUser &&
- this.currentUser.automatically_unpin_topics
+ this.currentUser.user_option.automatically_unpin_topics
) {
// automatically unpin topics when the user reaches the bottom
const max = Math.max(...postNumbers);
diff --git a/app/assets/javascripts/discourse/app/controllers/user-status.js b/app/assets/javascripts/discourse/app/controllers/user-status.js
index d9062b68786..554b783ff1d 100644
--- a/app/assets/javascripts/discourse/app/controllers/user-status.js
+++ b/app/assets/javascripts/discourse/app/controllers/user-status.js
@@ -84,7 +84,7 @@ export default Controller.extend(ModalFunctionality, {
},
_buildTimeShortcuts() {
- const timezone = this.currentUser.timezone;
+ const timezone = this.currentUser.user_option.timezone;
const shortcuts = timeShortcuts(timezone);
return [shortcuts.oneHour(), shortcuts.twoHours(), shortcuts.tomorrow()];
},
diff --git a/app/assets/javascripts/discourse/app/lib/click-track.js b/app/assets/javascripts/discourse/app/lib/click-track.js
index 52b45ec9b4e..05be231b7e5 100644
--- a/app/assets/javascripts/discourse/app/lib/click-track.js
+++ b/app/assets/javascripts/discourse/app/lib/click-track.js
@@ -54,7 +54,9 @@ export function isValidLink(link) {
export function shouldOpenInNewTab(href) {
const isInternal = DiscourseURL.isInternal(href);
- const openExternalInNewTab = User.currentProp("external_links_in_new_tab");
+ const openExternalInNewTab = User.currentProp(
+ "user_option.external_links_in_new_tab"
+ );
return !isInternal && openExternalInNewTab;
}
diff --git a/app/assets/javascripts/discourse/app/lib/download-calendar.js b/app/assets/javascripts/discourse/app/lib/download-calendar.js
index 49e289400ad..8aacdbaf184 100644
--- a/app/assets/javascripts/discourse/app/lib/download-calendar.js
+++ b/app/assets/javascripts/discourse/app/lib/download-calendar.js
@@ -8,7 +8,7 @@ export function downloadCalendar(title, dates) {
const formattedDates = formatDates(dates);
title = title.trim();
- switch (currentUser.default_calendar) {
+ switch (currentUser.user_option.default_calendar) {
case "none_selected":
_displayModal(title, formattedDates);
break;
diff --git a/app/assets/javascripts/discourse/app/lib/render-topic-featured-link.js b/app/assets/javascripts/discourse/app/lib/render-topic-featured-link.js
index 2d2c143a0e0..8520de95508 100644
--- a/app/assets/javascripts/discourse/app/lib/render-topic-featured-link.js
+++ b/app/assets/javascripts/discourse/app/lib/render-topic-featured-link.js
@@ -10,7 +10,9 @@ export function addFeaturedLinkMetaDecorator(decorator) {
export function extractLinkMeta(topic) {
const href = topic.get("featured_link");
- const target = User.currentProp("external_links_in_new_tab") ? "_blank" : "";
+ const target = User.currentProp("user_option.external_links_in_new_tab")
+ ? "_blank"
+ : "";
const domain = topic.get("featured_link_root_domain");
let allowList = topic.siteSettings.exclude_rel_nofollow_domains;
let rel = "nofollow ugc";
diff --git a/app/assets/javascripts/discourse/app/models/bookmark.js b/app/assets/javascripts/discourse/app/models/bookmark.js
index f6c059713ea..fb9a41b87e7 100644
--- a/app/assets/javascripts/discourse/app/models/bookmark.js
+++ b/app/assets/javascripts/discourse/app/models/bookmark.js
@@ -130,7 +130,10 @@ const Bookmark = RestModel.extend({
@discourseComputed("reminder_at", "currentUser")
formattedReminder(bookmarkReminderAt, currentUser) {
return capitalize(
- formattedReminderTime(bookmarkReminderAt, currentUser.timezone)
+ formattedReminderTime(
+ bookmarkReminderAt,
+ currentUser.user_option.timezone
+ )
);
},
diff --git a/app/assets/javascripts/discourse/app/models/user.js b/app/assets/javascripts/discourse/app/models/user.js
index 1a35abf31c1..d1d1b7d78f8 100644
--- a/app/assets/javascripts/discourse/app/models/user.js
+++ b/app/assets/javascripts/discourse/app/models/user.js
@@ -1,4 +1,5 @@
import EmberObject, { computed, get, getProperties } from "@ember/object";
+import { camelize } from "@ember/string";
import cookie, { removeCookie } from "discourse/lib/cookie";
import { defaultHomepage, escapeExpression } from "discourse/lib/utilities";
import {
@@ -130,15 +131,65 @@ export function addSaveableUserOptionField(fieldName) {
userOptionFields.push(fieldName);
}
+function userOption(userOptionKey) {
+ return computed(`user_option.${userOptionKey}`, {
+ get(key) {
+ deprecated(
+ `Getting ${key} property of user object is deprecated. Use user_option object instead`,
+ {
+ id: "discourse.user.userOptions",
+ since: "2.9.0.beta12",
+ dropFrom: "3.0.0.beta1",
+ }
+ );
+
+ return this.get(`user_option.${key}`);
+ },
+
+ set(key, value) {
+ deprecated(
+ `Setting ${key} property of user object is deprecated. Use user_option object instead`,
+ {
+ id: "discourse.user.userOptions",
+ since: "2.9.0.beta12",
+ dropFrom: "3.0.0.beta1",
+ }
+ );
+
+ if (!this.user_option) {
+ this.set("user_option", {});
+ }
+
+ return this.set(`user_option.${key}`, value);
+ },
+ });
+}
+
const User = RestModel.extend({
+ 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"),
+
hasPMs: gt("private_messages_stats.all", 0),
hasStartedPMs: gt("private_messages_stats.mine", 0),
hasUnreadPMs: gt("private_messages_stats.unread", 0),
- redirected_to_top: {
- reason: null,
- },
-
@discourseComputed("can_be_deleted", "post_count")
canBeDeleted(canBeDeleted, postCount) {
const maxPostCount = this.siteSettings.delete_all_posts_max;
@@ -376,20 +427,15 @@ const User = RestModel.extend({
userFields.filter((uf) => !fields || fields.includes(uf))
);
- let filteredUserOptionFields = [];
- if (fields) {
- filteredUserOptionFields = userOptionFields.filter((uo) =>
- fields.includes(uo)
- );
- } else {
- filteredUserOptionFields = userOptionFields;
- }
+ const filteredUserOptionFields = fields
+ ? userOptionFields.filter((uo) => fields.includes(uo))
+ : userOptionFields;
filteredUserOptionFields.forEach((s) => {
data[s] = this.get(`user_option.${s}`);
});
- let updatedState = {};
+ const updatedState = {};
["muted", "regular", "watched", "tracked", "watched_first_post"].forEach(
(categoryNotificationLevel) => {
@@ -397,23 +443,17 @@ const User = RestModel.extend({
fields === undefined ||
fields.includes(`${categoryNotificationLevel}_category_ids`)
) {
- let prop =
- categoryNotificationLevel === "watched_first_post"
- ? "watchedFirstPostCategories"
- : `${categoryNotificationLevel}Categories`;
+ const categories = this.get(
+ `${camelize(categoryNotificationLevel)}Categories`
+ );
- let cats = this.get(prop);
-
- if (cats) {
- let cat_ids = cats.map((c) => c.get("id"));
- updatedState[`${categoryNotificationLevel}_category_ids`] = cat_ids;
-
- // HACK: denote lack of categories
- if (cats.length === 0) {
- cat_ids = [-1];
- }
-
- data[`${categoryNotificationLevel}_category_ids`] = cat_ids;
+ if (categories) {
+ const ids = categories.map((c) => c.get("id"));
+ updatedState[`${categoryNotificationLevel}_category_ids`] = ids;
+ // HACK: Empty arrays are not sent in the request, we use [-1],
+ // an invalid category ID, that will be ignored by the server.
+ data[`${categoryNotificationLevel}_category_ids`] =
+ ids.length === 0 ? [-1] : ids;
}
}
}
@@ -436,10 +476,6 @@ const User = RestModel.extend({
}
});
- return this._saveUserData(data, updatedState);
- },
-
- _saveUserData(data, updatedState) {
// TODO: We can remove this when migrated fully to rest model.
this.set("isSaving", true);
return ajax(userPath(`${this.username_lower}.json`), {
@@ -449,19 +485,6 @@ const User = RestModel.extend({
.then((result) => {
this.setProperties(updatedState);
this.setProperties(getProperties(result.user, "bio_excerpt"));
- if (User.current() === this && result.user.user_option) {
- this.setProperties(
- getProperties(
- result.user.user_option,
- "enable_quoting",
- "enable_defer",
- "external_links_in_new_tab",
- "dynamic_favicon",
- "seen_popups",
- "skip_new_user_tips"
- )
- );
- }
return result;
})
.finally(() => {
@@ -1060,9 +1083,17 @@ const User = RestModel.extend({
);
},
- // obsolete, just call "user.timezone" instead
resolvedTimezone() {
- return this.timezone;
+ deprecated(
+ "user.resolvedTimezone() has been deprecated. Use user.user_option.timezone instead",
+ {
+ id: "discourse.user.resolved-timezone",
+ since: "2.9.0.beta12",
+ dropFrom: "3.0.0.beta1",
+ }
+ );
+
+ return this.user_option.timezone;
},
calculateMutedIds(notificationLevel, id, type) {
@@ -1199,12 +1230,10 @@ const User = RestModel.extend({
if (!this.user_option) {
this.set("user_option", {});
}
- this.set("seen_popups", seenUserTips);
this.set("user_option.seen_popups", seenUserTips);
if (userTipId) {
return this.save(["seen_popups"]);
} else {
- this.set("skip_new_user_tips", true);
this.set("user_option.skip_new_user_tips", true);
return this.save(["seen_popups", "skip_new_user_tips"]);
}
@@ -1233,8 +1262,8 @@ User.reopenClass(Singleton, {
}
}
- if (!userJson.timezone) {
- userJson.timezone = moment.tz.guess();
+ if (!userJson.user_option.timezone) {
+ userJson.user_option.timezone = moment.tz.guess();
this._saveTimezone(userJson);
}
@@ -1319,7 +1348,7 @@ User.reopenClass(Singleton, {
ajax(userPath(user.username + ".json"), {
type: "PUT",
dataType: "json",
- data: { timezone: user.timezone },
+ data: { timezone: user.user_option.timezone },
});
},
});
diff --git a/app/assets/javascripts/discourse/app/pre-initializers/dynamic-route-builders.js b/app/assets/javascripts/discourse/app/pre-initializers/dynamic-route-builders.js
index 9e7e070e045..b5b91a832cd 100644
--- a/app/assets/javascripts/discourse/app/pre-initializers/dynamic-route-builders.js
+++ b/app/assets/javascripts/discourse/app/pre-initializers/dynamic-route-builders.js
@@ -59,8 +59,16 @@ export default {
buildTopicRoute("top", {
actions: {
willTransition() {
- User.currentProp("should_be_redirected_to_top", false);
- User.currentProp("redirected_to_top.reason", null);
+ User.currentProp(
+ "user_option.should_be_redirected_to_top",
+ false
+ );
+ if (User.currentProp("user_option.redirected_to_top")) {
+ User.currentProp(
+ "user_option.redirected_to_top.reason",
+ null
+ );
+ }
return this._super(...arguments);
},
},
diff --git a/app/assets/javascripts/discourse/app/routes/discovery.js b/app/assets/javascripts/discourse/app/routes/discovery.js
index 9aa148d568d..d718a4da400 100644
--- a/app/assets/javascripts/discourse/app/routes/discovery.js
+++ b/app/assets/javascripts/discourse/app/routes/discovery.js
@@ -25,10 +25,11 @@ export default DiscourseRoute.extend(OpenComposer, {
if (
(url === "/" || url === "/latest" || url === "/categories") &&
!transition.targetName.includes("discovery.top") &&
- User.currentProp("should_be_redirected_to_top")
+ User.currentProp("user_option.should_be_redirected_to_top")
) {
- User.currentProp("should_be_redirected_to_top", false);
- const period = User.currentProp("redirected_to_top.period") || "all";
+ User.currentProp("user_option.should_be_redirected_to_top", false);
+ const period =
+ User.currentProp("user_option.redirected_to_top.period") || "all";
this.replaceWith("discovery.top", {
queryParams: {
period,
diff --git a/app/assets/javascripts/discourse/app/services/document-title.js b/app/assets/javascripts/discourse/app/services/document-title.js
index b4d0a4b4b1d..6e2869c62b7 100644
--- a/app/assets/javascripts/discourse/app/services/document-title.js
+++ b/app/assets/javascripts/discourse/app/services/document-title.js
@@ -73,7 +73,7 @@ export default Service.extend({
_displayCount() {
return this.currentUser &&
- this.currentUser.title_count_mode === "notifications"
+ this.currentUser.user_option.title_count_mode === "notifications"
? this.notificationCount
: this.contextCount;
},
@@ -82,12 +82,13 @@ export default Service.extend({
let title = this._title || this.siteSettings.title;
let displayCount = this._displayCount();
- let dynamicFavicon = this.currentUser && this.currentUser.dynamic_favicon;
+ let dynamicFavicon = this.currentUser?.user_option.dynamic_favicon;
- if (this.currentUser && this.currentUser.isInDoNotDisturb()) {
+ if (this.currentUser?.isInDoNotDisturb()) {
document.title = title;
return;
}
+
if (displayCount > 0 && !dynamicFavicon) {
title = `(${displayCount}) ${title}`;
}
@@ -96,7 +97,7 @@ export default Service.extend({
},
_renderFavicon() {
- if (this.currentUser && this.currentUser.dynamic_favicon) {
+ if (this.currentUser?.user_option.dynamic_favicon) {
let url = this.siteSettings.site_favicon_url;
// Since the favicon is cached on the browser for a really long time, we
diff --git a/app/assets/javascripts/discourse/app/widgets/post-menu.js b/app/assets/javascripts/discourse/app/widgets/post-menu.js
index 3b0e10f8b39..4eaa333b7cd 100644
--- a/app/assets/javascripts/discourse/app/widgets/post-menu.js
+++ b/app/assets/javascripts/discourse/app/widgets/post-menu.js
@@ -353,7 +353,7 @@ registerButton(
if (attrs.bookmarkReminderAt) {
let formattedReminder = formattedReminderTime(
attrs.bookmarkReminderAt,
- currentUser.timezone
+ currentUser.user_option.timezone
);
title = "bookmarks.created_with_reminder";
titleOptions.date = formattedReminder;
diff --git a/app/assets/javascripts/discourse/app/widgets/user-status-bubble.js b/app/assets/javascripts/discourse/app/widgets/user-status-bubble.js
index ec814670ad9..01dd33b7bf1 100644
--- a/app/assets/javascripts/discourse/app/widgets/user-status-bubble.js
+++ b/app/assets/javascripts/discourse/app/widgets/user-status-bubble.js
@@ -8,7 +8,7 @@ export default createWidget("user-status-bubble", {
let title = attrs.description;
if (attrs.ends_at) {
const until = moment
- .tz(attrs.ends_at, this.currentUser.timezone)
+ .tz(attrs.ends_at, this.currentUser.user_option.timezone)
.format(I18n.t("dates.long_date_without_year"));
title += `\n${I18n.t("until")} ${until}`;
}
diff --git a/app/assets/javascripts/discourse/tests/acceptance/admin-silence-user-test.js b/app/assets/javascripts/discourse/tests/acceptance/admin-silence-user-test.js
index 4d0f06f7e9d..ae6984c4a74 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/admin-silence-user-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/admin-silence-user-test.js
@@ -13,7 +13,7 @@ acceptance("Admin - Silence User", function (needs) {
needs.user();
needs.hooks.beforeEach(() => {
- const timezone = loggedInUser().timezone;
+ const timezone = loggedInUser().user_option.timezone;
clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning
});
diff --git a/app/assets/javascripts/discourse/tests/acceptance/admin-suspend-user-test.js b/app/assets/javascripts/discourse/tests/acceptance/admin-suspend-user-test.js
index 73918cd5e26..5e3c36be94c 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/admin-suspend-user-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/admin-suspend-user-test.js
@@ -112,7 +112,7 @@ acceptance("Admin - Suspend User - timeframe choosing", function (needs) {
needs.user();
needs.hooks.beforeEach(() => {
- const timezone = loggedInUser().timezone;
+ const timezone = loggedInUser().user_option.timezone;
clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning
});
diff --git a/app/assets/javascripts/discourse/tests/acceptance/bookmarks-test.js b/app/assets/javascripts/discourse/tests/acceptance/bookmarks-test.js
index e0c08690dd6..8a65eda13a4 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/bookmarks-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/bookmarks-test.js
@@ -170,7 +170,10 @@ acceptance("Bookmarking", function (needs) {
await selectKit(".bookmark-option-selector").selectRowByValue(1);
await click("#save-bookmark");
- assert.equal(User.current().bookmark_auto_delete_preference, "1");
+ assert.equal(
+ User.currentProp("user_option.bookmark_auto_delete_preference"),
+ "1"
+ );
await openEditBookmarkModal();
@@ -243,7 +246,7 @@ acceptance("Bookmarking", function (needs) {
test("Editing a bookmark", async function (assert) {
await visit("/t/internationalization-localization/280");
- let now = moment.tz(loggedInUser().timezone);
+ let now = moment.tz(loggedInUser().user_option.timezone);
let tomorrow = now.add(1, "day").format("YYYY-MM-DD");
await openBookmarkModal();
await fillIn("input#bookmark-name", "Test name");
@@ -269,7 +272,7 @@ acceptance("Bookmarking", function (needs) {
test("Using a post date for the reminder date", async function (assert) {
await visit("/t/internationalization-localization/280");
- let postDate = moment.tz("2036-01-15", loggedInUser().timezone);
+ let postDate = moment.tz("2036-01-15", loggedInUser().user_option.timezone);
let postDateFormatted = postDate.format("YYYY-MM-DD");
await openBookmarkModal();
await fillIn("input#bookmark-name", "Test name");
diff --git a/app/assets/javascripts/discourse/tests/acceptance/composer-editor-mentions-test.js b/app/assets/javascripts/discourse/tests/acceptance/composer-editor-mentions-test.js
index 29528b624a2..41f650c48ac 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/composer-editor-mentions-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/composer-editor-mentions-test.js
@@ -126,7 +126,7 @@ acceptance("Composer - editor mentions", function (needs) {
});
test("shows status on search results when mentioning a user", async function (assert) {
- const timezone = loggedInUser().timezone;
+ const timezone = loggedInUser().user_option.timezone;
const now = moment(status.ends_at).add(-1, "hour").format();
clock = fakeTime(now, timezone, true);
diff --git a/app/assets/javascripts/discourse/tests/acceptance/create-invite-modal-test.js b/app/assets/javascripts/discourse/tests/acceptance/create-invite-modal-test.js
index 0cc847176eb..ce818cb6fcd 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/create-invite-modal-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/create-invite-modal-test.js
@@ -191,7 +191,7 @@ acceptance(
});
needs.hooks.beforeEach(() => {
- const timezone = loggedInUser().timezone;
+ const timezone = loggedInUser().user_option.timezone;
clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning
});
diff --git a/app/assets/javascripts/discourse/tests/acceptance/redirect-to-top-test.js b/app/assets/javascripts/discourse/tests/acceptance/redirect-to-top-test.js
index ac40d43db0a..15e453e82e7 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/redirect-to-top-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/redirect-to-top-test.js
@@ -19,10 +19,12 @@ acceptance("Redirect to Top", function (needs) {
test("redirects categories to weekly top", async function (assert) {
updateCurrentUser({
- should_be_redirected_to_top: true,
- redirected_to_top: {
- period: "weekly",
- reason: "Welcome back!",
+ user_option: {
+ should_be_redirected_to_top: true,
+ redirected_to_top: {
+ period: "weekly",
+ reason: "Welcome back!",
+ },
},
});
@@ -36,10 +38,12 @@ acceptance("Redirect to Top", function (needs) {
test("redirects latest to monthly top", async function (assert) {
updateCurrentUser({
- should_be_redirected_to_top: true,
- redirected_to_top: {
- period: "monthly",
- reason: "Welcome back!",
+ user_option: {
+ should_be_redirected_to_top: true,
+ redirected_to_top: {
+ period: "monthly",
+ reason: "Welcome back!",
+ },
},
});
@@ -53,10 +57,12 @@ acceptance("Redirect to Top", function (needs) {
test("redirects root to All top", async function (assert) {
updateCurrentUser({
- should_be_redirected_to_top: true,
- redirected_to_top: {
- period: null,
- reason: "Welcome back!",
+ user_option: {
+ should_be_redirected_to_top: true,
+ redirected_to_top: {
+ period: null,
+ reason: "Welcome back!",
+ },
},
});
diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-bulk-actions-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-bulk-actions-test.js
index 9ff9d542dbc..0193efa0007 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/topic-bulk-actions-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/topic-bulk-actions-test.js
@@ -23,7 +23,10 @@ acceptance("Topic - Bulk Actions", function (needs) {
});
test("bulk select - modal", async function (assert) {
- updateCurrentUser({ moderator: true, enable_defer: true });
+ updateCurrentUser({
+ moderator: true,
+ user_option: { enable_defer: true },
+ });
await visit("/latest");
await click("button.bulk-select");
@@ -168,7 +171,13 @@ acceptance("Topic - Bulk Actions", function (needs) {
});
test("TL4 users can bulk select", async function (assert) {
- updateCurrentUser({ moderator: false, admin: false, trust_level: 4 });
+ updateCurrentUser({
+ moderator: false,
+ admin: false,
+ trust_level: 4,
+ user_option: { enable_defer: false },
+ });
+
await visit("/latest");
await click("button.bulk-select");
diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-edit-timer-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-edit-timer-test.js
index 39d77bdd8b4..7143b3002e1 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/topic-edit-timer-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/topic-edit-timer-test.js
@@ -31,7 +31,7 @@ acceptance("Topic - Edit timer", function (needs) {
});
needs.hooks.beforeEach(() => {
- const timezone = loggedInUser().timezone;
+ const timezone = loggedInUser().user_option.timezone;
const tuesday = "2100-06-15T08:00:00";
clock = fakeTime(tuesday, timezone, true);
});
diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-set-slow-mode-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-set-slow-mode-test.js
index e35eb72071f..890dc80b748 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/topic-set-slow-mode-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/topic-set-slow-mode-test.js
@@ -29,7 +29,7 @@ acceptance("Topic - Set Slow Mode", function (needs) {
});
needs.hooks.beforeEach(() => {
- const timezone = loggedInUser().timezone;
+ const timezone = loggedInUser().user_option.timezone;
clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning
});
diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-card-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-card-test.js
index bfd7611d4a5..43904e65b7b 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/user-card-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/user-card-test.js
@@ -12,11 +12,6 @@ import { cloneJSON } from "discourse-common/lib/object";
acceptance("User Card - Show Local Time", function (needs) {
needs.user();
needs.settings({ display_local_time_in_user_card: true });
- needs.pretender((server, helper) => {
- const cardResponse = cloneJSON(userFixtures["/u/charlie/card.json"]);
- delete cardResponse.user.timezone;
- server.get("/u/charlie/card.json", () => helper.response(cardResponse));
- });
test("user card local time - does not update timezone for another user", async function (assert) {
User.current().timezone = "Australia/Brisbane";
diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-preferences-notifications-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-preferences-notifications-test.js
index d107673ac20..b4f1996ba94 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/user-preferences-notifications-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/user-preferences-notifications-test.js
@@ -116,7 +116,7 @@ acceptance("User Notifications - Users - Ignore User", function (needs) {
needs.user();
needs.hooks.beforeEach(() => {
- const timezone = loggedInUser().timezone;
+ const timezone = loggedInUser().user_option.timezone;
clock = fakeTime("2100-05-03T08:00:00", timezone, true); // Monday morning
});
diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-preferences-profile-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-preferences-profile-test.js
index 1bf8cfa1f4e..344ff4b6071 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/user-preferences-profile-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/user-preferences-profile-test.js
@@ -5,6 +5,8 @@ import {
} from "discourse/tests/helpers/qunit-helpers";
import { click, visit } from "@ember/test-helpers";
import { test } from "qunit";
+import { cloneJSON } from "discourse-common/lib/object";
+import userFixtures from "discourse/tests/fixtures/user-fixtures";
acceptance("User - Preferences - Profile - Featured topic", function (needs) {
needs.user();
@@ -65,7 +67,15 @@ acceptance("User - Preferences - Profile - Featured topic", function (needs) {
acceptance(
"User - Preferences - Profile - No default calendar set",
function (needs) {
- needs.user({ default_calendar: "none_selected" });
+ needs.user();
+
+ needs.pretender((server, helper) => {
+ server.get("/u/eviltrout.json", () => {
+ const cloned = cloneJSON(userFixtures["/u/eviltrout.json"]);
+ cloned.user.user_option.default_calendar = "none_selected";
+ return helper.response(200, cloned);
+ });
+ });
test("default calendar option is not visible", async function (assert) {
await visit("/u/eviltrout/preferences/profile");
@@ -81,7 +91,15 @@ acceptance(
acceptance(
"User - Preferences - Profile - Default calendar set",
function (needs) {
- needs.user({ default_calendar: "google" });
+ needs.user();
+
+ needs.pretender((server, helper) => {
+ server.get("/u/eviltrout.json", () => {
+ const cloned = cloneJSON(userFixtures["/u/eviltrout.json"]);
+ cloned.user.user_option.default_calendar = "google";
+ return helper.response(200, cloned);
+ });
+ });
test("default calendar can be changed", async function (assert) {
await visit("/u/eviltrout/preferences/profile");
diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-preferences-tracking-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-preferences-tracking-test.js
index 92016c8e37e..81be6acbbf6 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/user-preferences-tracking-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/user-preferences-tracking-test.js
@@ -189,6 +189,8 @@ acceptance("User Preferences - Tracking", function (needs) {
await click(".save-changes");
assert.deepEqual(putRequestData, {
+ auto_track_topics_after_msecs: "60000",
+ new_topic_duration_minutes: "1440",
"regular_category_ids[]": ["-1"],
"tracked_category_ids[]": ["4"],
"watched_category_ids[]": ["3"],
@@ -211,6 +213,8 @@ acceptance("User Preferences - Tracking", function (needs) {
await click(".save-changes");
assert.deepEqual(putRequestData, {
+ auto_track_topics_after_msecs: "60000",
+ new_topic_duration_minutes: "1440",
"muted_category_ids[]": ["-1"],
"tracked_category_ids[]": ["4"],
"watched_category_ids[]": ["3"],
diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-status-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-status-test.js
index ccef190ca1e..9e8e0d14c51 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/user-status-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/user-status-test.js
@@ -26,7 +26,7 @@ acceptance("User Status", function (needs) {
const userId = 1;
const userTimezone = "UTC";
- needs.user({ id: userId, timezone: userTimezone });
+ needs.user({ id: userId, "user_option.timezone": userTimezone });
needs.pretender((server, helper) => {
server.put("/user-status.json", () => {
diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-test.js
index c84da617f8d..e8ce1fad39b 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/user-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/user-test.js
@@ -1,6 +1,5 @@
import I18n from "I18n";
import EmberObject from "@ember/object";
-import User from "discourse/models/user";
import selectKit from "discourse/tests/helpers/select-kit-helper";
import sinon from "sinon";
import userFixtures from "discourse/tests/fixtures/user-fixtures";
@@ -167,21 +166,33 @@ acceptance("User - Saving user options", function (needs) {
disable_mailing_list_mode: false,
});
+ let putRequestData;
+
needs.pretender((server, helper) => {
- server.put("/u/eviltrout.json", () => {
- return helper.response(200, { user: {} });
+ server.put("/u/eviltrout.json", (request) => {
+ putRequestData = helper.parsePostData(request.requestBody);
+ return helper.response({ user: {} });
});
});
- test("saving user options", async function (assert) {
- const spy = sinon.spy(User.current(), "_saveUserData");
+ needs.hooks.afterEach(() => {
+ putRequestData = null;
+ });
+ test("saving user options", async function (assert) {
await visit("/u/eviltrout/preferences/emails");
await click(".pref-mailing-list-mode input[type='checkbox']");
await click(".save-changes");
- assert.ok(
- spy.calledWithMatch({ mailing_list_mode: true }),
+ assert.deepEqual(
+ putRequestData,
+ {
+ digest_after_minutes: "10080",
+ email_digests: "true",
+ email_level: "1",
+ email_messages_level: "0",
+ mailing_list_mode: "true",
+ },
"sends a PUT request to update the specified user option"
);
@@ -189,8 +200,15 @@ acceptance("User - Saving user options", function (needs) {
await selectKit("#user-email-messages-level").selectRowByValue(2); // never option
await click(".save-changes");
- assert.ok(
- spy.calledWithMatch({ email_messages_level: 2 }),
+ assert.deepEqual(
+ putRequestData,
+ {
+ digest_after_minutes: "10080",
+ email_digests: "true",
+ email_level: "1",
+ email_messages_level: "2",
+ mailing_list_mode: "true",
+ },
"is able to save a different user_option on a subsequent request"
);
});
diff --git a/app/assets/javascripts/discourse/tests/fixtures/session-fixtures.js b/app/assets/javascripts/discourse/tests/fixtures/session-fixtures.js
index b5430580e8b..fe0c2dc870f 100644
--- a/app/assets/javascripts/discourse/tests/fixtures/session-fixtures.js
+++ b/app/assets/javascripts/discourse/tests/fixtures/session-fixtures.js
@@ -18,21 +18,14 @@ export default {
title: "co-founder",
reply_count: 859,
topic_count: 36,
- enable_quoting: true,
- external_links_in_new_tab: false,
- dynamic_favicon: true,
trust_level: 4,
can_edit: true,
can_invite_to_forum: true,
can_send_private_messages: true,
- should_be_redirected_to_top: false,
custom_fields: {},
muted_category_ids: [],
dismissed_banner_key: null,
akismet_review_count: 0,
- title_count_mode: "notifications",
- timezone: "Australia/Brisbane",
- skip_new_user_tips: false,
can_review: true,
ignored_users: [],
groups: [
@@ -48,7 +41,16 @@ export default {
name: "trust_level_1",
display_name: "trust_level_1",
}
- ]
+ ],
+ user_option: {
+ external_links_in_new_tab: false,
+ enable_quoting: true,
+ dynamic_favicon: true,
+ title_count_mode: "notifications",
+ timezone: "Australia/Brisbane",
+ skip_new_user_tips: false,
+ should_be_redirected_to_top: false,
+ },
},
},
};
diff --git a/app/assets/javascripts/discourse/tests/fixtures/user-fixtures.js b/app/assets/javascripts/discourse/tests/fixtures/user-fixtures.js
index 471f7c47fc9..979543af5d9 100644
--- a/app/assets/javascripts/discourse/tests/fixtures/user-fixtures.js
+++ b/app/assets/javascripts/discourse/tests/fixtures/user-fixtures.js
@@ -107,6 +107,18 @@ export default {
user: {
user_option: {
text_size_seq: 1,
+ email_digests: true,
+ email_messages_level: 0,
+ email_level: 1,
+ digest_after_minutes: 10080,
+ mailing_list_mode: false,
+ auto_track_topics_after_msecs: 60000,
+ new_topic_duration_minutes: 1440,
+ external_links_in_new_tab: false,
+ dynamic_favicon: true,
+ skip_new_user_tips: false,
+ enable_quoting: true,
+ timezone: "Australia/Brisbane",
},
id: 19,
username: "eviltrout",
@@ -166,17 +178,6 @@ export default {
can_be_deleted: false,
can_delete_all_posts: false,
locale: "",
- email_digests: true,
- email_messages_level: 0,
- email_level: 1,
- digest_after_minutes: 10080,
- mailing_list_mode: false,
- auto_track_topics_after_msecs: 60000,
- new_topic_duration_minutes: 1440,
- external_links_in_new_tab: false,
- dynamic_favicon: true,
- skip_new_user_tips: false,
- enable_quoting: true,
muted_category_ids: [],
regular_category_ids: [4],
tracked_category_ids: [],
@@ -294,7 +295,6 @@ export default {
day_6_start_time: 480,
day_6_end_time: 1020,
},
- timezone: "Australia/Brisbane",
has_topic_draft: true,
},
},
@@ -2722,8 +2722,8 @@ export default {
hide_profile_and_presence: false,
text_size: "normal",
text_size_seq: 0,
+ timezone: "America/Los_Angeles",
},
- timezone: "America/Los_Angeles",
},
},
"/u/charlie/card.json": {
@@ -3253,6 +3253,18 @@ export default {
user: {
user_option: {
text_size_seq: 1,
+ email_digests: true,
+ email_messages_level: 0,
+ email_level: 1,
+ digest_after_minutes: 10080,
+ mailing_list_mode: false,
+ auto_track_topics_after_msecs: 60000,
+ new_topic_duration_minutes: 1440,
+ external_links_in_new_tab: false,
+ dynamic_favicon: true,
+ skip_new_user_tips: false,
+ enable_quoting: true,
+ timezone: "Australia/Brisbane",
},
id: 4432,
username: "e.il.rout",
@@ -3312,17 +3324,6 @@ export default {
can_be_deleted: false,
can_delete_all_posts: false,
locale: "",
- email_digests: true,
- email_messages_level: 0,
- email_level: 1,
- digest_after_minutes: 10080,
- mailing_list_mode: false,
- auto_track_topics_after_msecs: 60000,
- new_topic_duration_minutes: 1440,
- external_links_in_new_tab: false,
- dynamic_favicon: true,
- skip_new_user_tips: false,
- enable_quoting: true,
muted_category_ids: [],
regular_category_ids: [],
tracked_category_ids: [],
@@ -3439,7 +3440,6 @@ export default {
day_6_start_time: 480,
day_6_end_time: 1020,
},
- timezone: "Australia/Brisbane",
},
},
"/u/staged.json": {
@@ -3470,6 +3470,18 @@ export default {
user: {
user_option: {
text_size_seq: 1,
+ email_digests: false,
+ email_messages_level: 0,
+ email_level: 1,
+ digest_after_minutes: 10080,
+ mailing_list_mode: false,
+ auto_track_topics_after_msecs: 60000,
+ new_topic_duration_minutes: 1440,
+ external_links_in_new_tab: false,
+ dynamic_favicon: true,
+ skip_new_user_tips: false,
+ enable_quoting: true,
+ timezone: "Australia/Brisbane",
},
id: 20,
username: "staged",
@@ -3509,17 +3521,6 @@ export default {
can_be_deleted: true,
can_delete_all_posts: true,
locale: "",
- email_digests: false,
- email_messages_level: 0,
- email_level: 1,
- digest_after_minutes: 10080,
- mailing_list_mode: false,
- auto_track_topics_after_msecs: 60000,
- new_topic_duration_minutes: 1440,
- external_links_in_new_tab: false,
- dynamic_favicon: true,
- skip_new_user_tips: false,
- enable_quoting: true,
muted_category_ids: [],
regular_category_ids: [],
tracked_category_ids: [],
@@ -3562,7 +3563,6 @@ export default {
day_6_start_time: 480,
day_6_end_time: 1020,
},
- timezone: "Australia/Brisbane",
},
},
"/u/recent-searches": {
diff --git a/app/assets/javascripts/discourse/tests/helpers/component-test.js b/app/assets/javascripts/discourse/tests/helpers/component-test.js
index 4e79dd558a1..f4e36d4c988 100644
--- a/app/assets/javascripts/discourse/tests/helpers/component-test.js
+++ b/app/assets/javascripts/discourse/tests/helpers/component-test.js
@@ -24,7 +24,6 @@ export function setupRenderingTest(hooks) {
const currentUser = User.create({
username: "eviltrout",
- timezone: "Australia/Brisbane",
name: "Robin Ward",
admin: false,
moderator: false,
@@ -42,6 +41,9 @@ export function setupRenderingTest(hooks) {
display_name: "trust_level_1",
},
],
+ user_option: {
+ timezone: "Australia/Brisbane",
+ },
});
this.currentUser = currentUser;
this.owner.unregister("service:current-user");
diff --git a/app/assets/javascripts/discourse/tests/integration/components/bookmark-icon-test.js b/app/assets/javascripts/discourse/tests/integration/components/bookmark-icon-test.js
index eeb58665f2c..5d277512ceb 100644
--- a/app/assets/javascripts/discourse/tests/integration/components/bookmark-icon-test.js
+++ b/app/assets/javascripts/discourse/tests/integration/components/bookmark-icon-test.js
@@ -14,7 +14,7 @@ module("Integration | Component | bookmark-icon", function (hooks) {
test("with reminder", async function (assert) {
this.setProperties({
bookmark: Bookmark.create({
- reminder_at: tomorrow(this.currentUser.timezone),
+ reminder_at: tomorrow(this.currentUser.user_option.timezone),
name: "some name",
}),
});
@@ -29,7 +29,7 @@ module("Integration | Component | bookmark-icon", function (hooks) {
I18n.t("bookmarks.created_with_reminder_generic", {
date: formattedReminderTime(
this.bookmark.reminder_at,
- this.currentUser.timezone
+ this.currentUser.user_option.timezone
),
name: "some name",
})
diff --git a/app/assets/javascripts/discourse/tests/integration/components/d-document-test.js b/app/assets/javascripts/discourse/tests/integration/components/d-document-test.js
index 361c55b5707..885818fbdbc 100644
--- a/app/assets/javascripts/discourse/tests/integration/components/d-document-test.js
+++ b/app/assets/javascripts/discourse/tests/integration/components/d-document-test.js
@@ -23,7 +23,7 @@ module("Integration | Component | d-document", function (hooks) {
const titleBefore = document.title;
try {
this.currentUser.redesigned_user_menu_enabled = true;
- this.currentUser.title_count_mode = "notifications";
+ this.currentUser.user_option.title_count_mode = "notifications";
await render(hbs``);
assert.strictEqual(
getTitleCount(),
@@ -51,7 +51,7 @@ module("Integration | Component | d-document", function (hooks) {
const titleBefore = document.title;
try {
this.currentUser.redesigned_user_menu_enabled = false;
- this.currentUser.title_count_mode = "notifications";
+ this.currentUser.user_option.title_count_mode = "notifications";
await render(hbs``);
assert.strictEqual(
getTitleCount(),
diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/future-date-input-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/future-date-input-test.js
index 8d7af274cdb..b652adc4699 100644
--- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/future-date-input-test.js
+++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/future-date-input-test.js
@@ -58,7 +58,11 @@ module(
test("renders default options", async function (assert) {
const monday = "2100-12-13T08:00:00";
- this.clock = fakeTime(monday, this.currentUser.timezone, true);
+ this.clock = fakeTime(
+ monday,
+ this.currentUser.user_option.timezone,
+ true
+ );
await render(hbs``);
diff --git a/app/assets/javascripts/discourse/tests/integration/components/time-shortcut-picker-test.js b/app/assets/javascripts/discourse/tests/integration/components/time-shortcut-picker-test.js
index d1ecae1de27..cc53e4dec8d 100644
--- a/app/assets/javascripts/discourse/tests/integration/components/time-shortcut-picker-test.js
+++ b/app/assets/javascripts/discourse/tests/integration/components/time-shortcut-picker-test.js
@@ -29,7 +29,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("shows default options", async function (assert) {
this.siteSettings.suggest_weekends_in_date_pickers = true;
const tuesday = "2100-06-08T08:00:00";
- this.clock = fakeTime(tuesday, this.currentUser.timezone, true);
+ this.clock = fakeTime(tuesday, this.currentUser.user_option.timezone, true);
await render(hbs``);
@@ -55,7 +55,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("show 'Later This Week' if today is < Thursday", async function (assert) {
const monday = "2100-06-07T08:00:00";
- this.clock = fakeTime(monday, this.currentUser.timezone, true);
+ this.clock = fakeTime(monday, this.currentUser.user_option.timezone, true);
await render(hbs``);
@@ -64,7 +64,11 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("does not show 'Later This Week' if today is >= Thursday", async function (assert) {
const thursday = "2100-06-10T08:00:00";
- this.clock = fakeTime(thursday, this.currentUser.timezone, true);
+ this.clock = fakeTime(
+ thursday,
+ this.currentUser.user_option.timezone,
+ true
+ );
await render(hbs``);
@@ -77,7 +81,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("does not show 'Later Today' if 'Later Today' is tomorrow", async function (assert) {
this.clock = fakeTime(
"2100-12-11T22:00:00", // + 3 hours is tomorrow
- this.currentUser.timezone,
+ this.currentUser.user_option.timezone,
true
);
@@ -92,7 +96,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("shows 'Later Today' if it is before 5pm", async function (assert) {
this.clock = fakeTime(
"2100-12-11T16:50:00",
- this.currentUser.timezone,
+ this.currentUser.user_option.timezone,
true
);
@@ -104,7 +108,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("does not show 'Later Today' if it is after 5pm", async function (assert) {
this.clock = fakeTime(
"2100-12-11T17:00:00",
- this.currentUser.timezone,
+ this.currentUser.user_option.timezone,
true
);
@@ -119,7 +123,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("default custom date time is in one hour from now", async function (assert) {
this.clock = fakeTime(
"2100-12-11T17:00:00",
- this.currentUser.timezone,
+ this.currentUser.user_option.timezone,
true
);
@@ -132,7 +136,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("shows 'Next Monday' instead of 'Monday' on Sundays", async function (assert) {
const sunday = "2100-01-24T08:00:00";
- this.clock = fakeTime(sunday, this.currentUser.timezone, true);
+ this.clock = fakeTime(sunday, this.currentUser.user_option.timezone, true);
await render(hbs``);
@@ -150,7 +154,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("shows 'Next Monday' instead of 'Monday' on Mondays", async function (assert) {
const monday = "2100-01-25T08:00:00";
- this.clock = fakeTime(monday, this.currentUser.timezone, true);
+ this.clock = fakeTime(monday, this.currentUser.user_option.timezone, true);
await render(hbs``);
@@ -169,7 +173,7 @@ module("Integration | Component | time-shortcut-picker", function (hooks) {
test("the 'Next Month' option points to the first day of the next month", async function (assert) {
this.clock = fakeTime(
"2100-01-01T08:00:00",
- this.currentUser.timezone,
+ this.currentUser.user_option.timezone,
true
);
diff --git a/app/assets/javascripts/discourse/tests/integration/components/user-menu/menu-test.js b/app/assets/javascripts/discourse/tests/integration/components/user-menu/menu-test.js
index 14dbaaba8d2..562784895f2 100644
--- a/app/assets/javascripts/discourse/tests/integration/components/user-menu/menu-test.js
+++ b/app/assets/javascripts/discourse/tests/integration/components/user-menu/menu-test.js
@@ -64,7 +64,7 @@ module("Integration | Component | user-menu", function (hooks) {
});
test("likes tab is hidden if current user's like notifications frequency is 'never'", async function (assert) {
- this.currentUser.set("likes_notifications_disabled", true);
+ this.currentUser.set("user_option.likes_notifications_disabled", true);
this.currentUser.set("can_send_private_messages", true);
await render(template);
assert.ok(!exists("#user-menu-button-likes"));
diff --git a/app/assets/javascripts/discourse/tests/integration/components/user-status-message-test.js b/app/assets/javascripts/discourse/tests/integration/components/user-status-message-test.js
index aa87d173649..82364918ab1 100644
--- a/app/assets/javascripts/discourse/tests/integration/components/user-status-message-test.js
+++ b/app/assets/javascripts/discourse/tests/integration/components/user-status-message-test.js
@@ -12,7 +12,7 @@ module("Integration | Component | user-status-message", function (hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function () {
- this.currentUser.timezone = "UTC";
+ this.currentUser.user_option.timezone = "UTC";
});
hooks.afterEach(function () {
@@ -49,7 +49,7 @@ module("Integration | Component | user-status-message", function (hooks) {
test("it shows the until TIME on the tooltip if status will expire today", async function (assert) {
this.clock = fakeTime(
"2100-02-01T08:00:00.000Z",
- this.currentUser.timezone,
+ this.currentUser.user_option.timezone,
true
);
this.set("status", {
@@ -72,7 +72,7 @@ module("Integration | Component | user-status-message", function (hooks) {
test("it shows the until DATE on the tooltip if status will expire tomorrow", async function (assert) {
this.clock = fakeTime(
"2100-02-01T08:00:00.000Z",
- this.currentUser.timezone,
+ this.currentUser.user_option.timezone,
true
);
this.set("status", {
@@ -95,7 +95,7 @@ module("Integration | Component | user-status-message", function (hooks) {
test("it doesn't show until datetime on the tooltip if status doesn't have expiration date", async function (assert) {
this.clock = fakeTime(
"2100-02-01T08:00:00.000Z",
- this.currentUser.timezone,
+ this.currentUser.user_option.timezone,
true
);
this.set("status", {
diff --git a/app/assets/javascripts/discourse/tests/unit/lib/click-track-test.js b/app/assets/javascripts/discourse/tests/unit/lib/click-track-test.js
index 67e8ea605b5..669568a93bc 100644
--- a/app/assets/javascripts/discourse/tests/unit/lib/click-track-test.js
+++ b/app/assets/javascripts/discourse/tests/unit/lib/click-track-test.js
@@ -137,7 +137,7 @@ module("Unit | Utility | click-track", function (hooks) {
skip("tracks external URLs when opening in another window", async function (assert) {
assert.expect(3);
- User.currentProp("external_links_in_new_tab", true);
+ User.currentProp("user_option.external_links_in_new_tab", true);
const done = assert.async();
pretender.post("/clicks/track", (request) => {
@@ -171,7 +171,7 @@ module("Unit | Utility | click-track", function (hooks) {
});
test("does not track clicks links in quotes", async function (assert) {
- User.currentProp("external_links_in_new_tab", true);
+ User.currentProp("user_option.external_links_in_new_tab", true);
assert.notOk(track(generateClickEventOn(".quote a:last-child")));
assert.ok(window.open.calledWith("https://google.com/", "_blank"));
});
diff --git a/app/assets/javascripts/discourse/tests/unit/models/user-test.js b/app/assets/javascripts/discourse/tests/unit/models/user-test.js
index a0a25c22601..51b51d5c20a 100644
--- a/app/assets/javascripts/discourse/tests/unit/models/user-test.js
+++ b/app/assets/javascripts/discourse/tests/unit/models/user-test.js
@@ -94,14 +94,14 @@ module("Unit | Model | user", function (hooks) {
test("createCurrent() guesses timezone if user doesn't have it set", async function (assert) {
PreloadStore.store("currentUser", {
username: "eviltrout",
- timezone: null,
+ user_option: { timezone: null },
});
const expectedTimezone = "Africa/Casablanca";
sinon.stub(moment.tz, "guess").returns(expectedTimezone);
const currentUser = User.createCurrent();
- assert.deepEqual(currentUser.timezone, expectedTimezone);
+ assert.deepEqual(currentUser.user_option.timezone, expectedTimezone);
await settled(); // `User` sends a request to save the timezone
});
@@ -110,7 +110,7 @@ module("Unit | Model | user", function (hooks) {
const timezone = "Africa/Casablanca";
PreloadStore.store("currentUser", {
username: "eviltrout",
- timezone,
+ user_option: { timezone },
});
const spyMomentGuess = sinon.spy(moment.tz, "guess");
diff --git a/app/assets/javascripts/discourse/tests/unit/services/document-title-test.js b/app/assets/javascripts/discourse/tests/unit/services/document-title-test.js
index 5fc5919f6bc..d058c42569c 100644
--- a/app/assets/javascripts/discourse/tests/unit/services/document-title-test.js
+++ b/app/assets/javascripts/discourse/tests/unit/services/document-title-test.js
@@ -34,7 +34,7 @@ module("Unit | Service | document-title", function (hooks) {
test("it displays notification counts for logged in users", function (assert) {
this.documentTitle.currentUser = currentUser();
- this.documentTitle.currentUser.dynamic_favicon = false;
+ this.documentTitle.currentUser.user_option.dynamic_favicon = false;
this.documentTitle.setTitle("test notifications");
this.documentTitle.updateNotificationCount(5);
assert.strictEqual(document.title, "test notifications");
@@ -52,7 +52,7 @@ module("Unit | Service | document-title", function (hooks) {
date.setHours(date.getHours() + 1);
this.documentTitle.currentUser.do_not_disturb_until = date.toUTCString();
- this.documentTitle.currentUser.dynamic_favicon = false;
+ this.documentTitle.currentUser.user_option.dynamic_favicon = false;
this.documentTitle.setTitle("test notifications");
this.documentTitle.updateNotificationCount(5);
assert.strictEqual(document.title, "test notifications");
diff --git a/app/assets/javascripts/select-kit/addon/components/future-date-input-selector.js b/app/assets/javascripts/select-kit/addon/components/future-date-input-selector.js
index e294171f655..4141d8393c3 100644
--- a/app/assets/javascripts/select-kit/addon/components/future-date-input-selector.js
+++ b/app/assets/javascripts/select-kit/addon/components/future-date-input-selector.js
@@ -18,7 +18,7 @@ export default ComboBoxComponent.extend({
init() {
this._super(...arguments);
- this.userTimezone = this.currentUser.timezone;
+ this.userTimezone = this.currentUser.user_option.timezone;
},
modifyComponentForRow() {
diff --git a/app/assets/javascripts/select-kit/addon/components/topic-notifications-button.js b/app/assets/javascripts/select-kit/addon/components/topic-notifications-button.js
index d56dd51a69b..8927c096141 100644
--- a/app/assets/javascripts/select-kit/addon/components/topic-notifications-button.js
+++ b/app/assets/javascripts/select-kit/addon/components/topic-notifications-button.js
@@ -61,7 +61,7 @@ export default Component.extend({
if (
this.currentUser &&
- this.currentUser.mailing_list_mode &&
+ this.currentUser.user_option.mailing_list_mode &&
level > NotificationLevels.MUTED
) {
return I18n.t("topic.notifications.reasons.mailing_list_mode");
diff --git a/app/serializers/current_user_option_serializer.rb b/app/serializers/current_user_option_serializer.rb
new file mode 100644
index 00000000000..edfabcf3d6c
--- /dev/null
+++ b/app/serializers/current_user_option_serializer.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class CurrentUserOptionSerializer < ApplicationSerializer
+ attributes :mailing_list_mode,
+ :external_links_in_new_tab,
+ :enable_quoting,
+ :dynamic_favicon,
+ :automatically_unpin_topics,
+ :likes_notifications_disabled,
+ :hide_profile_and_presence,
+ :title_count_mode,
+ :enable_defer,
+ :timezone,
+ :skip_new_user_tips,
+ :default_calendar,
+ :bookmark_auto_delete_preference,
+ :seen_popups,
+ :should_be_redirected_to_top,
+ :redirected_to_top,
+ :treat_as_new_topic_start_date,
+
+ def likes_notifications_disabled
+ object.likes_notifications_disabled?
+ end
+
+ def include_redirected_to_top?
+ object.redirected_to_top.present?
+ end
+
+ def include_seen_popups?
+ SiteSetting.enable_user_tips
+ end
+end
diff --git a/app/serializers/current_user_serializer.rb b/app/serializers/current_user_serializer.rb
index 278f432965c..e620cb711d8 100644
--- a/app/serializers/current_user_serializer.rb
+++ b/app/serializers/current_user_serializer.rb
@@ -17,10 +17,6 @@ class CurrentUserSerializer < BasicUserSerializer
:whisperer?,
:title,
:any_posts,
- :enable_quoting,
- :enable_defer,
- :external_links_in_new_tab,
- :dynamic_favicon,
:trust_level,
:can_send_private_email_messages,
:can_send_private_messages,
@@ -28,8 +24,6 @@ class CurrentUserSerializer < BasicUserSerializer
:can_invite_to_forum,
:no_password,
:can_delete_account,
- :should_be_redirected_to_top,
- :redirected_to_top,
:custom_fields,
:muted_category_ids,
:indirectly_muted_category_ids,
@@ -48,9 +42,6 @@ class CurrentUserSerializer < BasicUserSerializer
:unseen_reviewable_count,
:new_personal_messages_notifications_count,
:read_faq?,
- :automatically_unpin_topics,
- :mailing_list_mode,
- :treat_as_new_topic_start_date,
:previous_visit_at,
:seen_notification_id,
:primary_group_id,
@@ -61,25 +52,17 @@ class CurrentUserSerializer < BasicUserSerializer
:external_id,
:associated_account_ids,
:top_category_ids,
- :hide_profile_and_presence,
:groups,
:second_factor_enabled,
:ignored_users,
- :title_count_mode,
- :timezone,
:featured_topic,
- :skip_new_user_tips,
- :seen_popups,
:do_not_disturb_until,
:has_topic_draft,
:can_review,
:draft_count,
- :default_calendar,
- :bookmark_auto_delete_preference,
:pending_posts_count,
:status,
:sidebar_category_ids,
- :likes_notifications_disabled,
:grouped_unread_notifications,
:redesigned_user_menu_enabled,
:redesigned_user_page_nav_enabled,
@@ -89,6 +72,8 @@ class CurrentUserSerializer < BasicUserSerializer
delegate :user_stat, to: :object, private: true
delegate :any_posts, :draft_count, :pending_posts_count, :read_faq?, to: :user_stat
+ has_one :user_option, embed: :object, serializer: CurrentUserOptionSerializer
+
def groups
owned_group_ids = GroupUser.where(user_id: id, owner: true).pluck(:group_id).to_set
@@ -115,54 +100,6 @@ class CurrentUserSerializer < BasicUserSerializer
scope.can_create_group?
end
- def hide_profile_and_presence
- object.user_option.hide_profile_and_presence
- end
-
- def enable_quoting
- object.user_option.enable_quoting
- end
-
- def enable_defer
- object.user_option.enable_defer
- end
-
- def external_links_in_new_tab
- object.user_option.external_links_in_new_tab
- end
-
- def dynamic_favicon
- object.user_option.dynamic_favicon
- end
-
- def title_count_mode
- object.user_option.title_count_mode
- end
-
- def automatically_unpin_topics
- object.user_option.automatically_unpin_topics
- end
-
- def should_be_redirected_to_top
- object.user_option.should_be_redirected_to_top
- end
-
- def redirected_to_top
- object.user_option.redirected_to_top
- end
-
- def timezone
- object.user_option.timezone
- end
-
- def default_calendar
- object.user_option.default_calendar
- end
-
- def bookmark_auto_delete_preference
- object.user_option.bookmark_auto_delete_preference
- end
-
def sidebar_list_destination
object.user_option.sidebar_list_none_selected? ? SiteSetting.default_sidebar_list_destination : object.user_option.sidebar_list_destination
end
@@ -203,10 +140,6 @@ class CurrentUserSerializer < BasicUserSerializer
true
end
- def include_redirected_to_top?
- object.user_option.redirected_to_top.present?
- end
-
def custom_fields
fields = nil
if SiteSetting.public_user_custom_fields.present?
@@ -278,26 +211,6 @@ class CurrentUserSerializer < BasicUserSerializer
scope.can_see_review_queue?
end
- def mailing_list_mode
- object.user_option.mailing_list_mode
- end
-
- def treat_as_new_topic_start_date
- object.user_option.treat_as_new_topic_start_date
- end
-
- def skip_new_user_tips
- object.user_option.skip_new_user_tips
- end
-
- def seen_popups
- object.user_option.seen_popups
- end
-
- def include_seen_popups?
- SiteSetting.enable_user_tips
- end
-
def include_primary_group_id?
object.primary_group_id.present?
end
@@ -364,10 +277,6 @@ class CurrentUserSerializer < BasicUserSerializer
object.redesigned_user_menu_enabled?
end
- def likes_notifications_disabled
- object.user_option&.likes_notifications_disabled?
- end
-
def include_all_unread_notifications_count?
redesigned_user_menu_enabled
end
diff --git a/plugins/chat/assets/javascripts/discourse/helpers/format-chat-date.js b/plugins/chat/assets/javascripts/discourse/helpers/format-chat-date.js
index 9c0a1be4d76..6226d541ed1 100644
--- a/plugins/chat/assets/javascripts/discourse/helpers/format-chat-date.js
+++ b/plugins/chat/assets/javascripts/discourse/helpers/format-chat-date.js
@@ -7,9 +7,7 @@ import User from "discourse/models/user";
registerUnbound("format-chat-date", function (message, details, mode) {
let currentUser = User.current();
- let tz = currentUser
- ? currentUser.resolvedTimezone(currentUser)
- : moment.tz.guess();
+ let tz = currentUser ? currentUser.user_option.timezone : moment.tz.guess();
let date = moment(new Date(message.created_at), tz);
diff --git a/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js b/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js
index 333a026f38f..ee754a1e75e 100644
--- a/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js
+++ b/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js
@@ -66,8 +66,7 @@ export default {
api.decorateCookedElement(
(elem) => {
const currentUser = getOwner(this).lookup("service:current-user");
- const currentUserTimezone =
- currentUser?.resolvedTimezone(currentUser);
+ const currentUserTimezone = currentUser?.user_option?.timezone;
const chatTranscriptElements =
elem.querySelectorAll(".chat-transcript");
diff --git a/plugins/chat/assets/javascripts/discourse/initializers/chat-sidebar.js b/plugins/chat/assets/javascripts/discourse/initializers/chat-sidebar.js
index 1081ee1355c..e7c417e8e1e 100644
--- a/plugins/chat/assets/javascripts/discourse/initializers/chat-sidebar.js
+++ b/plugins/chat/assets/javascripts/discourse/initializers/chat-sidebar.js
@@ -383,7 +383,7 @@ export default {
if (status.ends_at) {
const untilFormatted = until(
status.ends_at,
- this.chatService.currentUser.timezone,
+ this.chatService.currentUser.user_option.timezone,
this.chatService.currentUser.locale
);
title += ` ${untilFormatted}`;
diff --git a/plugins/discourse-local-dates/test/javascripts/acceptance/download-calendar-test.js b/plugins/discourse-local-dates/test/javascripts/acceptance/download-calendar-test.js
index f3f5eb5914a..7f5588a7b6f 100644
--- a/plugins/discourse-local-dates/test/javascripts/acceptance/download-calendar-test.js
+++ b/plugins/discourse-local-dates/test/javascripts/acceptance/download-calendar-test.js
@@ -13,7 +13,7 @@ import { cloneJSON } from "discourse-common/lib/object";
acceptance(
"Local Dates - Download calendar without default calendar option set",
function (needs) {
- needs.user({ default_calendar: "none_selected" });
+ needs.user({ "user_option.default_calendar": "none_selected" });
needs.settings({ discourse_local_dates_enabled: true });
needs.pretender((server, helper) => {
const response = cloneJSON(fixturesByUrl["/t/281.json"]);
@@ -43,7 +43,7 @@ acceptance(
acceptance(
"Local Dates - Download calendar is not available for dates in the past",
function (needs) {
- needs.user({ default_calendar: "none_selected" });
+ needs.user({ "user_option.default_calendar": "none_selected" });
needs.settings({ discourse_local_dates_enabled: true });
needs.pretender((server, helper) => {
const response = cloneJSON(fixturesByUrl["/t/281.json"]);
@@ -69,7 +69,7 @@ acceptance(
acceptance(
"Local Dates - Download calendar with default calendar option set",
function (needs) {
- needs.user({ default_calendar: "google" });
+ needs.user({ "user_option.default_calendar": "google" });
needs.settings({ discourse_local_dates_enabled: true });
needs.pretender((server, helper) => {
const response = cloneJSON(fixturesByUrl["/t/281.json"]);
diff --git a/plugins/discourse-presence/assets/javascripts/discourse/services/composer-presence-manager.js b/plugins/discourse-presence/assets/javascripts/discourse/services/composer-presence-manager.js
index e302a3a585c..b7dc90084ea 100644
--- a/plugins/discourse-presence/assets/javascripts/discourse/services/composer-presence-manager.js
+++ b/plugins/discourse-presence/assets/javascripts/discourse/services/composer-presence-manager.js
@@ -11,7 +11,7 @@ export default class ComposerPresenceManager extends Service {
notifyState(intent, id) {
if (
this.siteSettings.allow_users_to_hide_profile &&
- this.currentUser.hide_profile_and_presence
+ this.currentUser.user_option.hide_profile_and_presence
) {
return;
}
diff --git a/spec/serializers/current_user_serializer_spec.rb b/spec/serializers/current_user_serializer_spec.rb
index 0c6f92b3a60..cc6a04290d9 100644
--- a/spec/serializers/current_user_serializer_spec.rb
+++ b/spec/serializers/current_user_serializer_spec.rb
@@ -331,16 +331,16 @@ RSpec.describe CurrentUserSerializer do
describe "#likes_notifications_disabled" do
it "is true if the user disables likes notifications" do
user.user_option.update!(like_notification_frequency: UserOption.like_notification_frequency_type[:never])
- expect(serializer.as_json[:likes_notifications_disabled]).to eq(true)
+ expect(serializer.as_json[:user_option][:likes_notifications_disabled]).to eq(true)
end
it "is false if the user doesn't disable likes notifications" do
user.user_option.update!(like_notification_frequency: UserOption.like_notification_frequency_type[:always])
- expect(serializer.as_json[:likes_notifications_disabled]).to eq(false)
+ expect(serializer.as_json[:user_option][:likes_notifications_disabled]).to eq(false)
user.user_option.update!(like_notification_frequency: UserOption.like_notification_frequency_type[:first_time_and_daily])
- expect(serializer.as_json[:likes_notifications_disabled]).to eq(false)
+ expect(serializer.as_json[:user_option][:likes_notifications_disabled]).to eq(false)
user.user_option.update!(like_notification_frequency: UserOption.like_notification_frequency_type[:first_time])
- expect(serializer.as_json[:likes_notifications_disabled]).to eq(false)
+ expect(serializer.as_json[:user_option][:likes_notifications_disabled]).to eq(false)
end
end