From b10f156250e3b982d8b7200479279cbb85069f1d Mon Sep 17 00:00:00 2001 From: MariaGkoulta Date: Sat, 16 May 2020 14:13:59 +0300 Subject: [PATCH] settings: Add automatic theme detection feature. With this implementation of the feature of the automatic theme detection, we make the following changes in the backend, frontend and documentation. This replaces the previous night_mode boolean with an enum, with the default value being to use the prefers-color-scheme feature of the operating system to determine which theme to use. Fixes: #14451. Co-authored-by: @kPerikou <44238834+kPerikou@users.noreply.github.com> --- frontend_tests/node_tests/dispatch.js | 22 ++++++++---- frontend_tests/node_tests/lib/events.js | 18 ++++++---- static/js/night_mode.js | 8 +++-- static/js/realm_logo.js | 8 ++++- static/js/server_events_dispatch.js | 13 ++++--- static/js/settings.js | 2 +- static/js/settings_config.js | 16 ++++++++- static/js/settings_display.js | 9 ++++- static/styles/night_mode.scss | 6 ++++ .../templates/settings/display_settings.hbs | 8 +++++ templates/zerver/api/changelog.md | 5 +++ templates/zerver/base.html | 2 +- templates/zerver/help/night-mode.md | 16 ++++++--- version.py | 2 +- zerver/lib/zcommand.py | 14 ++++---- ...0290_remove_night_mode_add_color_scheme.py | 35 +++++++++++++++++++ zerver/models.py | 12 +++++-- zerver/tests/test_events.py | 1 + zerver/tests/test_home.py | 18 +++++----- zerver/tests/test_middleware.py | 5 ++- zerver/tests/test_settings.py | 1 + zerver/tests/test_users.py | 9 ++--- zerver/tests/test_zcommand.py | 5 +-- zerver/views/home.py | 8 ++--- zerver/views/user_settings.py | 3 +- 25 files changed, 185 insertions(+), 61 deletions(-) create mode 100644 zerver/migrations/0290_remove_night_mode_add_color_scheme.py diff --git a/frontend_tests/node_tests/dispatch.js b/frontend_tests/node_tests/dispatch.js index 639c988f27..dacc3cee16 100644 --- a/frontend_tests/node_tests/dispatch.js +++ b/frontend_tests/node_tests/dispatch.js @@ -692,20 +692,30 @@ with_overrides(function (override) { $("body").fadeIn = (secs) => { assert_same(secs, 300); }; global.with_stub(function (stub) { - event = event_fixtures.update_display_settings__night_mode; - page_params.night_mode = false; + event = event_fixtures.update_display_settings__color_scheme_dark; + page_params.color_scheme = 1; override('night_mode.enable', stub.f); // automatically checks if called override('realm_logo.rerender', noop); dispatch(event); - assert_same(page_params.night_mode, true); + assert(page_params.color_scheme, 2); }); global.with_stub(function (stub) { - event = event_fixtures.update_display_settings__night_mode_false; - page_params.night_mode = true; + event = event_fixtures.update_display_settings__color_scheme_light; + page_params.color_scheme = 1; override('night_mode.disable', stub.f); // automatically checks if called + override('realm_logo.rerender', noop); dispatch(event); - assert(!page_params.night_mode); + assert(page_params.color_scheme, 3); + }); + + global.with_stub(function (stub) { + event = event_fixtures.update_display_settings__color_scheme_automatic; + page_params.color_scheme = 2; + override('night_mode.default_preference_checker', stub.f); // automatically checks if called + override('realm_logo.rerender', noop); + dispatch(event); + assert(page_params.color_scheme, 1); }); global.with_stub(function (stub) { diff --git a/frontend_tests/node_tests/lib/events.js b/frontend_tests/node_tests/lib/events.js index 58cba6964b..78c761ad1e 100644 --- a/frontend_tests/node_tests/lib/events.js +++ b/frontend_tests/node_tests/lib/events.js @@ -478,16 +478,22 @@ exports.fixtures = { setting: true, }, - update_display_settings__night_mode: { + update_display_settings__color_scheme_automatic: { type: 'update_display_settings', - setting_name: 'night_mode', - setting: true, + setting_name: 'color_scheme', + setting: 1, }, - update_display_settings__night_mode_false: { + update_display_settings__color_scheme_dark: { type: 'update_display_settings', - setting_name: 'night_mode', - setting: false, + setting_name: 'color_scheme', + setting: 2, + }, + + update_display_settings__color_scheme_light: { + type: 'update_display_settings', + setting_name: 'color_scheme', + setting: 3, }, update_display_settings__starred_message_counts: { diff --git a/static/js/night_mode.js b/static/js/night_mode.js index 2dec1fd6ba..3b32690ec1 100644 --- a/static/js/night_mode.js +++ b/static/js/night_mode.js @@ -1,9 +1,13 @@ exports.enable = function () { - $("body").addClass("night-mode"); + $("body").removeClass("color-scheme-automatic").addClass("night-mode"); }; exports.disable = function () { - $("body").removeClass("night-mode"); + $("body").removeClass("color-scheme-automatic").removeClass("night-mode"); +}; + +exports.default_preference_checker = function () { + $("body").removeClass("night-mode").addClass("color-scheme-automatic"); }; window.night_mode = exports; diff --git a/static/js/realm_logo.js b/static/js/realm_logo.js index f067ba15b7..479573d9cf 100644 --- a/static/js/realm_logo.js +++ b/static/js/realm_logo.js @@ -1,3 +1,5 @@ +const settings_config = require("./settings_config"); + exports.build_realm_logo_widget = function (upload_function, is_night) { let logo_section_id = '#realm-day-logo-upload-widget'; let logo_source = page_params.realm_logo_source; @@ -73,7 +75,11 @@ exports.rerender = function () { $("#realm-night-logo-upload-widget .image-block").attr("src", page_params.realm_night_logo_url); } - if (page_params.night_mode && page_params.realm_night_logo_source !== 'D') { + if (page_params.color_scheme === settings_config.color_scheme_values.night.code && + page_params.realm_night_logo_source !== 'D' || + page_params.color_scheme === settings_config.color_scheme_values.automatic.code && + page_params.realm_night_logo_source !== 'D' && + (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)) { $("#realm-logo").attr("src", page_params.realm_night_logo_url); } else { $("#realm-logo").attr("src", page_params.realm_logo_url); diff --git a/static/js/server_events_dispatch.js b/static/js/server_events_dispatch.js index 6272f5e6d9..164e9cb149 100644 --- a/static/js/server_events_dispatch.js +++ b/static/js/server_events_dispatch.js @@ -1,3 +1,5 @@ +const settings_config = require("./settings_config"); + exports.dispatch_normal_event = function dispatch_normal_event(event) { const noop = function () {}; switch (event.type) { @@ -395,13 +397,13 @@ exports.dispatch_normal_event = function dispatch_normal_event(event) { case 'update_display_settings': { const user_display_settings = [ + 'color_scheme', 'default_language', 'demote_inactive_streams', 'dense_mode', 'emojiset', 'fluid_layout_width', 'high_contrast_mode', - 'night_mode', 'left_side_userlist', 'timezone', 'twenty_four_hour_time', @@ -433,15 +435,18 @@ exports.dispatch_normal_event = function dispatch_normal_event(event) { $("body").toggleClass("less_dense_mode"); $("body").toggleClass("more_dense_mode"); } - if (event.setting_name === 'night_mode') { + if (event.setting_name === 'color_scheme') { $("body").fadeOut(300); setTimeout(function () { - if (event.setting === true) { + if (event.setting === settings_config.color_scheme_values.night.code) { night_mode.enable(); realm_logo.rerender(); - } else { + } else if (event.setting === settings_config.color_scheme_values.day.code) { night_mode.disable(); realm_logo.rerender(); + } else { + night_mode.default_preference_checker(); + realm_logo.rerender(); } $("body").fadeIn(300); }, 300); diff --git a/static/js/settings.js b/static/js/settings.js index fbbf5c9b0e..883f45ea04 100644 --- a/static/js/settings.js +++ b/static/js/settings.js @@ -37,7 +37,6 @@ function setup_settings_label() { fluid_layout_width: i18n.t("Use full width on wide screens"), high_contrast_mode: i18n.t("High contrast mode"), left_side_userlist: i18n.t("Show user list on left sidebar in narrow windows"), - night_mode: i18n.t("Night mode"), starred_message_counts: i18n.t("Show counts for starred messages"), twenty_four_hour_time: i18n.t("Time format"), translate_emoticons: i18n.t("Convert emoticons before sending (:) becomes 😃)"), @@ -58,6 +57,7 @@ exports.build_page = function () { can_create_new_bots: settings_bots.can_create_new_bots(), settings_label: exports.settings_label, demote_inactive_streams_values: settings_config.demote_inactive_streams_values, + color_scheme_values: settings_config.color_scheme_values, twenty_four_hour_time_values: settings_config.twenty_four_hour_time_values, general_settings: settings_config.all_notifications().general_settings, notification_settings: settings_config.all_notifications().settings, diff --git a/static/js/settings_config.js b/static/js/settings_config.js index 25a4854f97..3ecc1e99ad 100644 --- a/static/js/settings_config.js +++ b/static/js/settings_config.js @@ -27,6 +27,21 @@ exports.demote_inactive_streams_values = { }, }; +exports.color_scheme_values = { + automatic: { + code: 1, + description: i18n.t("Automatic"), + }, + night: { + code: 2, + description: i18n.t("Night mode"), + }, + day: { + code: 3, + description: i18n.t("Day mode"), + }, +}; + exports.twenty_four_hour_time_values = { twenty_four_hour_clock: { value: true, @@ -42,7 +57,6 @@ exports.get_all_display_settings = () => ({ settings: { user_display_settings: [ "dense_mode", - "night_mode", "high_contrast_mode", "left_side_userlist", "starred_message_counts", diff --git a/static/js/settings_display.js b/static/js/settings_display.js index 28667d5f06..1bb5d6c759 100644 --- a/static/js/settings_display.js +++ b/static/js/settings_display.js @@ -29,6 +29,8 @@ exports.set_up = function () { $("#demote_inactive_streams").val(page_params.demote_inactive_streams); + $("#color_scheme").val(page_params.color_scheme); + $("#twenty_four_hour_time").val(JSON.stringify(page_params.twenty_four_hour_time)); $(".emojiset_choice[value=" + page_params.emojiset + "]").prop("checked", true); @@ -82,6 +84,11 @@ exports.set_up = function () { change_display_setting(data, '#display-settings-status'); }); + $('#color_scheme').change(function () { + const data = {color_scheme: this.value}; + change_display_setting(data, '#display-settings-status'); + }); + $('body').on('click', '.reload_link', function () { window.location.reload(); }); @@ -146,8 +153,8 @@ exports.update_page = function () { $("#left_side_userlist").prop('checked', page_params.left_side_userlist); $("#default_language_name").text(page_params.default_language_name); $("#translate_emoticons").prop('checked', page_params.translate_emoticons); - $("#night_mode").prop('checked', page_params.night_mode); $("#twenty_four_hour_time").val(JSON.stringify(page_params.twenty_four_hour_time)); + $("#color_scheme").val(JSON.stringify(page_params.color_scheme)); // TODO: Set emojiset selector here. // Longer term, we'll want to automate this function diff --git a/static/styles/night_mode.scss b/static/styles/night_mode.scss index 90a2440258..885d0271dd 100644 --- a/static/styles/night_mode.scss +++ b/static/styles/night_mode.scss @@ -786,3 +786,9 @@ on a dark background, and don't change the dark labels dark either. */ background-color: hsla(0, 0%, 0%, 0.2); } } + +@media (prefers-color-scheme: dark) { + .color-scheme-automatic { + @extend body.night-mode; + } +} diff --git a/static/templates/settings/display_settings.hbs b/static/templates/settings/display_settings.hbs index f9e9478943..2cca09ebef 100644 --- a/static/templates/settings/display_settings.hbs +++ b/static/templates/settings/display_settings.hbs @@ -21,6 +21,14 @@

{{t "Display settings" }}

+
+ + +
+ {{#each display_settings.settings.user_display_settings}} {{> settings_checkbox setting_name=this diff --git a/templates/zerver/api/changelog.md b/templates/zerver/api/changelog.md index 84843f0637..b99d94f825 100644 --- a/templates/zerver/api/changelog.md +++ b/templates/zerver/api/changelog.md @@ -10,6 +10,11 @@ below features are supported. ## Changes in Zulip 2.2 +**Feature level 21** + +* `PATCH /settings/display`: Replaced the `night_mode` boolean with + `color_scheme` as part of supporting automatic night theme detection. + **Feature level 20** * Added support for inviting users as organization owners to the diff --git a/templates/zerver/base.html b/templates/zerver/base.html index 6958ff7c2c..d043093720 100644 --- a/templates/zerver/base.html +++ b/templates/zerver/base.html @@ -29,7 +29,7 @@ {% endblock %} - + {% block content %} {% endblock %} diff --git a/templates/zerver/help/night-mode.md b/templates/zerver/help/night-mode.md index f6de1bff80..7001568929 100644 --- a/templates/zerver/help/night-mode.md +++ b/templates/zerver/help/night-mode.md @@ -1,15 +1,21 @@ # Night mode -By default, Zulip has a white background. Zulip also provides a -"night mode", which is great for working in a dark space. +Zulip provides both a light theme and a night theme, which is great +for working in a dark space. -### Enable night mode +## Manage color theme {start_tabs} {settings_tab|display-settings} -2. Under **Display settings**, select **Night mode**. +2. Under **Display settings**, configure **Color scheme**. {end_tabs} -. + +The default is **Automatic**, which detects which theme to use based +on the color scheme used by your operating system. + +You can also specifc **Night mode** or **Day mode** if you'd like +Zulip to use the same color scheme regardless of your operating system +configuration. diff --git a/version.py b/version.py index cab5abf5d8..a6b6dd7e51 100644 --- a/version.py +++ b/version.py @@ -29,7 +29,7 @@ DESKTOP_WARNING_VERSION = "5.2.0" # # Changes should be accompanied by documentation explaining what the # new level means in templates/zerver/api/changelog.md. -API_FEATURE_LEVEL = 20 +API_FEATURE_LEVEL = 21 # Bump the minor PROVISION_VERSION to indicate that folks should provision # only when going from an old version of the code to a newer version. Bump diff --git a/zerver/lib/zcommand.py b/zerver/lib/zcommand.py index 16beb63894..14ed4b9179 100644 --- a/zerver/lib/zcommand.py +++ b/zerver/lib/zcommand.py @@ -9,7 +9,7 @@ from zerver.models import UserProfile def process_zcommands(content: str, user_profile: UserProfile) -> Dict[str, Any]: def change_mode_setting(command: str, switch_command: str, - setting: str, setting_value: bool) -> str: + setting: str, setting_value: int) -> str: msg = 'Changed to {command} mode! To revert ' \ '{command} mode, type `/{switch_command}`.'.format( command=command, @@ -27,19 +27,19 @@ def process_zcommands(content: str, user_profile: UserProfile) -> Dict[str, Any] if command == 'ping': return dict() elif command == 'night': - if user_profile.night_mode: + if user_profile.color_scheme == UserProfile.COLOR_SCHEME_NIGHT: return dict(msg='You are still in night mode.') return dict(msg=change_mode_setting(command=command, switch_command='day', - setting='night_mode', - setting_value=True)) + setting='color_scheme', + setting_value=UserProfile.COLOR_SCHEME_NIGHT)) elif command == 'day': - if not user_profile.night_mode: + if user_profile.color_scheme == UserProfile.COLOR_SCHEME_LIGHT: return dict(msg='You are still in day mode.') return dict(msg=change_mode_setting(command=command, switch_command='night', - setting='night_mode', - setting_value=False)) + setting='color_scheme', + setting_value=UserProfile.COLOR_SCHEME_LIGHT)) elif command == 'fluid-width': if user_profile.fluid_layout_width: return dict(msg='You are still in fluid width mode.') diff --git a/zerver/migrations/0290_remove_night_mode_add_color_scheme.py b/zerver/migrations/0290_remove_night_mode_add_color_scheme.py new file mode 100644 index 0000000000..644cd02485 --- /dev/null +++ b/zerver/migrations/0290_remove_night_mode_add_color_scheme.py @@ -0,0 +1,35 @@ +# Generated by Django 2.2.13 on 2020-06-20 15:22 + +from django.db import migrations, models +from django.db.backends.postgresql.schema import DatabaseSchemaEditor +from django.db.migrations.state import StateApps + +COLOR_SCHEME_AUTOMATIC = 1 +COLOR_SCHEME_NIGHT = 2 + +# Set color_scheme to night mode, if night_mode is True. +def set_color_scheme_to_night_mode(apps: StateApps, schema_editor: DatabaseSchemaEditor) -> None: + UserProfile = apps.get_model("zerver", "UserProfile") + UserProfile.objects.filter(night_mode=True).update(color_scheme=COLOR_SCHEME_NIGHT) + +class Migration(migrations.Migration): + + dependencies = [ + ('zerver', '0289_tighten_attachment_size'), + ] + + operations = [ + migrations.AddField( + model_name='userprofile', + name='color_scheme', + field=models.PositiveSmallIntegerField(default=COLOR_SCHEME_AUTOMATIC), + ), + migrations.RunPython( + set_color_scheme_to_night_mode, + reverse_code=migrations.RunPython.noop, + elidable=True), + migrations.RemoveField( + model_name='userprofile', + name='night_mode', + ), + ] diff --git a/zerver/models.py b/zerver/models.py index ba1682f7b7..2898184b47 100644 --- a/zerver/models.py +++ b/zerver/models.py @@ -999,10 +999,18 @@ class UserProfile(AbstractBaseUser, PermissionsMixin): dense_mode: bool = models.BooleanField(default=True) fluid_layout_width: bool = models.BooleanField(default=False) high_contrast_mode: bool = models.BooleanField(default=False) - night_mode: bool = models.BooleanField(default=False) translate_emoticons: bool = models.BooleanField(default=False) twenty_four_hour_time: bool = models.BooleanField(default=False) starred_message_counts: bool = models.BooleanField(default=False) + COLOR_SCHEME_AUTOMATIC = 1 + COLOR_SCHEME_NIGHT = 2 + COLOR_SCHEME_LIGHT = 3 + COLOR_SCHEME_CHOICES = [ + COLOR_SCHEME_AUTOMATIC, + COLOR_SCHEME_NIGHT, + COLOR_SCHEME_LIGHT + ] + color_scheme = models.PositiveSmallIntegerField(default=COLOR_SCHEME_AUTOMATIC) # UI setting controlling Zulip's behavior of demoting in the sort # order and graying out streams with no recent traffic. The @@ -1069,6 +1077,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin): # Define the types of the various automatically managed properties property_types = dict( + color_scheme=int, default_language=str, demote_inactive_streams=int, dense_mode=bool, @@ -1076,7 +1085,6 @@ class UserProfile(AbstractBaseUser, PermissionsMixin): fluid_layout_width=bool, high_contrast_mode=bool, left_side_userlist=bool, - night_mode=bool, starred_message_counts=bool, timezone=str, translate_emoticons=bool, diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py index 6242765a88..d9a2756a22 100644 --- a/zerver/tests/test_events.py +++ b/zerver/tests/test_events.py @@ -1852,6 +1852,7 @@ class EventsRegisterTest(ZulipTestCase): default_language = ['es', 'de', 'en'], timezone = ['US/Mountain', 'US/Samoa', 'Pacific/Galapogos', ''], demote_inactive_streams = [2, 3, 1], + color_scheme = [2, 3, 1] ) property_type = UserProfile.property_types[setting_name] diff --git a/zerver/tests/test_home.py b/zerver/tests/test_home.py index cd9b0b3985..ad8b148a63 100644 --- a/zerver/tests/test_home.py +++ b/zerver/tests/test_home.py @@ -61,6 +61,7 @@ class HomeTest(ZulipTestCase): "bot_types", "can_create_streams", "can_subscribe_other_users", + "color_scheme", "cross_realm_bots", "custom_profile_field_types", "custom_profile_fields", @@ -117,7 +118,6 @@ class HomeTest(ZulipTestCase): "narrow_stream", "needs_tutorial", "never_subscribed", - "night_mode", "notification_sound", "password_min_guesses", "password_min_length", @@ -761,34 +761,34 @@ class HomeTest(ZulipTestCase): def test_compute_navbar_logo_url(self) -> None: user_profile = self.example_user("hamlet") - page_params = {"night_mode": True} + page_params = {"color_scheme": user_profile.COLOR_SCHEME_NIGHT} add_realm_logo_fields(page_params, user_profile.realm) self.assertEqual(compute_navbar_logo_url(page_params), "/static/images/logo/zulip-org-logo.png?version=0") - page_params = {"night_mode": False} + page_params = {"color_scheme": user_profile.COLOR_SCHEME_LIGHT} add_realm_logo_fields(page_params, user_profile.realm) self.assertEqual(compute_navbar_logo_url(page_params), "/static/images/logo/zulip-org-logo.png?version=0") do_change_logo_source(user_profile.realm, Realm.LOGO_UPLOADED, night=False) - page_params = {"night_mode": True} + page_params = {"color_scheme": user_profile.COLOR_SCHEME_NIGHT} add_realm_logo_fields(page_params, user_profile.realm) self.assertEqual(compute_navbar_logo_url(page_params), f"/user_avatars/{user_profile.realm_id}/realm/logo.png?version=2") - page_params = {"night_mode": False} + page_params = {"color_scheme": user_profile.COLOR_SCHEME_LIGHT} add_realm_logo_fields(page_params, user_profile.realm) self.assertEqual(compute_navbar_logo_url(page_params), f"/user_avatars/{user_profile.realm_id}/realm/logo.png?version=2") do_change_logo_source(user_profile.realm, Realm.LOGO_UPLOADED, night=True) - page_params = {"night_mode": True} + page_params = {"color_scheme": user_profile.COLOR_SCHEME_NIGHT} add_realm_logo_fields(page_params, user_profile.realm) self.assertEqual(compute_navbar_logo_url(page_params), f"/user_avatars/{user_profile.realm_id}/realm/night_logo.png?version=2") - page_params = {"night_mode": False} + page_params = {"color_scheme": user_profile.COLOR_SCHEME_LIGHT} add_realm_logo_fields(page_params, user_profile.realm) self.assertEqual(compute_navbar_logo_url(page_params), f"/user_avatars/{user_profile.realm_id}/realm/logo.png?version=2") @@ -796,12 +796,12 @@ class HomeTest(ZulipTestCase): # This configuration isn't super supported in the UI and is a # weird choice, but we have a test for it anyway. do_change_logo_source(user_profile.realm, Realm.LOGO_DEFAULT, night=False) - page_params = {"night_mode": True} + page_params = {"color_scheme": user_profile.COLOR_SCHEME_NIGHT} add_realm_logo_fields(page_params, user_profile.realm) self.assertEqual(compute_navbar_logo_url(page_params), f"/user_avatars/{user_profile.realm_id}/realm/night_logo.png?version=2") - page_params = {"night_mode": False} + page_params = {"color_scheme": user_profile.COLOR_SCHEME_LIGHT} add_realm_logo_fields(page_params, user_profile.realm) self.assertEqual(compute_navbar_logo_url(page_params), "/static/images/logo/zulip-org-logo.png?version=0") diff --git a/zerver/tests/test_middleware.py b/zerver/tests/test_middleware.py index 6506b73f04..694d064d71 100644 --- a/zerver/tests/test_middleware.py +++ b/zerver/tests/test_middleware.py @@ -83,9 +83,8 @@ class OpenGraphTest(ZulipTestCase): self.check_title_and_description( '/help/night-mode', "Night mode (Zulip Help Center)", - ['By default, Zulip has a white background. ', - 'Zulip also provides a "night mode", which is great for working in a dark space.'], - [], + ['Zulip provides both a white background and a "night mode", which is great for working in a dark space.'], + [] ) def test_settings_tab(self) -> None: diff --git a/zerver/tests/test_settings.py b/zerver/tests/test_settings.py index 246ae6f687..9626c5104f 100644 --- a/zerver/tests/test_settings.py +++ b/zerver/tests/test_settings.py @@ -322,6 +322,7 @@ class ChangeSettingsTest(ZulipTestCase): emojiset = 'google', timezone = 'US/Mountain', demote_inactive_streams = 2, + color_scheme = 2, ) self.login('hamlet') diff --git a/zerver/tests/test_users.py b/zerver/tests/test_users.py index f2d2f6ec8b..58df104385 100644 --- a/zerver/tests/test_users.py +++ b/zerver/tests/test_users.py @@ -1020,11 +1020,12 @@ class UserProfileTest(ZulipTestCase): iago = self.example_user("iago") cordelia = self.example_user("cordelia") hamlet = self.example_user("hamlet") + hamlet.color_scheme = UserProfile.COLOR_SCHEME_LIGHT cordelia.default_language = "de" cordelia.emojiset = "twitter" cordelia.timezone = "America/Phoenix" - cordelia.night_mode = True + cordelia.color_scheme = UserProfile.COLOR_SCHEME_NIGHT cordelia.enable_offline_email_notifications = False cordelia.enable_stream_push_notifications = True cordelia.enter_sends = False @@ -1055,9 +1056,9 @@ class UserProfileTest(ZulipTestCase): self.assertEqual(cordelia.timezone, "America/Phoenix") self.assertEqual(hamlet.timezone, "") - self.assertEqual(iago.night_mode, True) - self.assertEqual(cordelia.night_mode, True) - self.assertEqual(hamlet.night_mode, False) + self.assertEqual(iago.color_scheme, UserProfile.COLOR_SCHEME_NIGHT) + self.assertEqual(cordelia.color_scheme, UserProfile.COLOR_SCHEME_NIGHT) + self.assertEqual(hamlet.color_scheme, UserProfile.COLOR_SCHEME_LIGHT) self.assertEqual(iago.enable_offline_email_notifications, False) self.assertEqual(cordelia.enable_offline_email_notifications, False) diff --git a/zerver/tests/test_zcommand.py b/zerver/tests/test_zcommand.py index 08c1ca7d16..abf2afc134 100644 --- a/zerver/tests/test_zcommand.py +++ b/zerver/tests/test_zcommand.py @@ -1,4 +1,5 @@ from zerver.lib.test_classes import ZulipTestCase +from zerver.models import UserProfile class ZcommandTest(ZulipTestCase): @@ -24,7 +25,7 @@ class ZcommandTest(ZulipTestCase): def test_night_zcommand(self) -> None: self.login('hamlet') user = self.example_user('hamlet') - user.night_mode = False + user.color_scheme = UserProfile.COLOR_SCHEME_LIGHT user.save() payload = dict(command="/night") @@ -39,7 +40,7 @@ class ZcommandTest(ZulipTestCase): def test_day_zcommand(self) -> None: self.login('hamlet') user = self.example_user('hamlet') - user.night_mode = True + user.color_scheme = UserProfile.COLOR_SCHEME_NIGHT user.save() payload = dict(command="/day") diff --git a/zerver/views/home.py b/zerver/views/home.py index 3976b15073..04d4174a79 100644 --- a/zerver/views/home.py +++ b/zerver/views/home.py @@ -129,7 +129,7 @@ def get_bot_types(user_profile: Optional[UserProfile]) -> List[Dict[str, object] return bot_types def compute_navbar_logo_url(page_params: Dict[str, Any]) -> str: - if page_params["night_mode"] and page_params["realm_night_logo_source"] != Realm.LOGO_DEFAULT: + if page_params["color_scheme"] == 2 and page_params["realm_night_logo_source"] != Realm.LOGO_DEFAULT: navbar_logo_url = page_params["realm_night_logo_url"] else: navbar_logo_url = page_params["realm_logo_url"] @@ -315,13 +315,13 @@ def home_real(request: HttpRequest) -> HttpResponse: csp_nonce = generate_random_token(48) if user_profile is not None: - night_mode = user_profile.night_mode + color_scheme = user_profile.color_scheme is_guest = user_profile.is_guest is_realm_owner = user_profile.is_realm_owner is_realm_admin = user_profile.is_realm_admin show_webathena = user_profile.realm.webathena_enabled else: # nocoverage - night_mode = False + color_scheme = UserProfile.COLOR_SCHEME_AUTOMATIC is_guest = False is_realm_admin = False is_realm_owner = False @@ -342,7 +342,7 @@ def home_real(request: HttpRequest) -> HttpResponse: 'is_owner': is_realm_owner, 'is_admin': is_realm_admin, 'is_guest': is_guest, - 'night_mode': night_mode, + 'color_scheme': color_scheme, 'navbar_logo_url': navbar_logo_url, 'show_webathena': show_webathena, 'embedded': narrow_stream is not None, diff --git a/zerver/views/user_settings.py b/zerver/views/user_settings.py index 8575bf8e82..db10ab4376 100644 --- a/zerver/views/user_settings.py +++ b/zerver/views/user_settings.py @@ -165,7 +165,8 @@ def update_display_settings_backend( starred_message_counts: Optional[bool]=REQ(validator=check_bool, default=None), fluid_layout_width: Optional[bool]=REQ(validator=check_bool, default=None), high_contrast_mode: Optional[bool]=REQ(validator=check_bool, default=None), - night_mode: Optional[bool]=REQ(validator=check_bool, default=None), + color_scheme: Optional[int]=REQ(validator=check_int_in( + UserProfile.COLOR_SCHEME_CHOICES), default=None), translate_emoticons: Optional[bool]=REQ(validator=check_bool, default=None), default_language: Optional[str]=REQ(validator=check_string, default=None), left_side_userlist: Optional[bool]=REQ(validator=check_bool, default=None),