diff --git a/frontend_tests/node_tests/dispatch.js b/frontend_tests/node_tests/dispatch.js index 77eb3d3101..909e3255ce 100644 --- a/frontend_tests/node_tests/dispatch.js +++ b/frontend_tests/node_tests/dispatch.js @@ -676,6 +676,20 @@ run_test("update_display_settings", (override) => { assert(page_params.color_scheme, 3); } + { + event = event_fixtures.update_display_settings__default_view_recent_topics; + page_params.default_view = "all_messages"; + dispatch(event); + assert(page_params.default_view, "recent_topics"); + } + + { + event = event_fixtures.update_display_settings__default_view_all_messages; + page_params.default_view = "recent_topics"; + dispatch(event); + assert(page_params.default_view, "all_messages"); + } + { const stub = make_stub(); event = event_fixtures.update_display_settings__color_scheme_automatic; diff --git a/frontend_tests/node_tests/lib/events.js b/frontend_tests/node_tests/lib/events.js index afd2884164..5364903e8d 100644 --- a/frontend_tests/node_tests/lib/events.js +++ b/frontend_tests/node_tests/lib/events.js @@ -610,6 +610,20 @@ exports.fixtures = { user: test_user.email, }, + update_display_settings__default_view_all_messages: { + type: "update_display_settings", + setting_name: "default_view", + setting: 1, + user: test_user.email, + }, + + update_display_settings__default_view_recent_topics: { + type: "update_display_settings", + setting_name: "default_view", + setting: "recent_topics", + user: test_user.email, + }, + update_display_settings__demote_inactive_streams: { type: "update_display_settings", setting_name: "demote_inactive_streams", diff --git a/static/js/hashchange.js b/static/js/hashchange.js index 4fdc4baabf..c5d5ec7069 100644 --- a/static/js/hashchange.js +++ b/static/js/hashchange.js @@ -59,7 +59,7 @@ function maybe_hide_recent_topics() { } export function in_recent_topics_hash() { - return ["recent_topics", "#", ""].includes(window.location.hash); + return ["#recent_topics"].includes(window.location.hash); } export function changehash(newhash) { @@ -114,6 +114,10 @@ function is_overlay_hash(hash) { return overlay_list.includes(main_hash); } +export function show_default_view() { + window.location.hash = page_params.default_view; +} + // Returns true if this function performed a narrow function do_hashchange_normal(from_reload) { message_viewport.stop_auto_scrolling(); @@ -130,8 +134,7 @@ function do_hashchange_normal(from_reload) { if (operators === undefined) { // If the narrow URL didn't parse, clear // window.location.hash and send them to the home tab - set_hash("#all_messages"); - activate_home_tab(); + show_default_view(); return false; } const narrow_opts = { @@ -152,6 +155,8 @@ function do_hashchange_normal(from_reload) { } case "": case "#": + show_default_view(); + break; case "#recent_topics": recent_topics.show(); break; @@ -176,6 +181,9 @@ function do_hashchange_overlay(old_hash) { if (old_hash === undefined) { // User directly requested to open an overlay. // We need to show recent topics in the background. + // Even though recent topics may not be the default view + // here, we show it because we need to show a view in + // background and recent topics seems preferrable for that. recent_topics.show(); } const base = hash_util.get_hash_category(window.location.hash); diff --git a/static/js/hotkey.js b/static/js/hotkey.js index dd3d0c24cc..3ba548f271 100644 --- a/static/js/hotkey.js +++ b/static/js/hotkey.js @@ -305,7 +305,7 @@ export function process_escape_key(e) { return true; } - hashchange.go_to_location(""); + hashchange.show_default_view(); return true; } @@ -770,7 +770,7 @@ export function process_hotkey(e, hotkey) { narrow.narrow_to_next_pm_string(); return true; case "open_recent_topics": - hashchange.go_to_location("#"); + hashchange.go_to_location("#recent_topics"); return true; case "all_messages": hashchange.go_to_location("#all_messages"); diff --git a/static/js/recent_topics.js b/static/js/recent_topics.js index a29c4ca6d9..a0ae0e9ce4 100644 --- a/static/js/recent_topics.js +++ b/static/js/recent_topics.js @@ -564,10 +564,13 @@ export function change_focused_element(e, input_key) { } switch (input_key) { + // Allow broswer to handle all + // character keypresses. case "vim_left": case "vim_right": case "vim_down": case "vim_up": + case "open_recent_topics": return false; case "shift_tab": current_focus_elem = filter_buttons().last(); diff --git a/static/js/server_events_dispatch.js b/static/js/server_events_dispatch.js index 51154249b9..c6441ac230 100644 --- a/static/js/server_events_dispatch.js +++ b/static/js/server_events_dispatch.js @@ -445,6 +445,7 @@ export function dispatch_normal_event(event) { const user_display_settings = [ "color_scheme", "default_language", + "default_view", "demote_inactive_streams", "dense_mode", "emojiset", diff --git a/static/js/settings.js b/static/js/settings.js index 7d8449912d..9bd32fc75d 100644 --- a/static/js/settings.js +++ b/static/js/settings.js @@ -83,6 +83,7 @@ export function build_page() { settings_label, demote_inactive_streams_values: settings_config.demote_inactive_streams_values, color_scheme_values: settings_config.color_scheme_values, + default_view_values: settings_config.default_view_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 95a19bff41..6cb7047d7d 100644 --- a/static/js/settings_config.js +++ b/static/js/settings_config.js @@ -28,6 +28,17 @@ export const demote_inactive_streams_values = { }, }; +export const default_view_values = { + recent_topics: { + code: "recent_topics", + description: i18n.t("Recent topics"), + }, + all_messages: { + code: "all_messages", + description: i18n.t("All messages"), + }, +}; + export const color_scheme_values = { automatic: { code: 1, diff --git a/static/js/settings_display.js b/static/js/settings_display.js index 6c8ef5bffb..cd68a80f11 100644 --- a/static/js/settings_display.js +++ b/static/js/settings_display.js @@ -42,6 +42,8 @@ export function set_up() { $("#color_scheme").val(page_params.color_scheme); + $("#default_view").val(page_params.default_view); + $("#twenty_four_hour_time").val(JSON.stringify(page_params.twenty_four_hour_time)); $(`.emojiset_choice[value="${CSS.escape(page_params.emojiset)}"]`).prop("checked", true); @@ -109,6 +111,11 @@ export function set_up() { change_display_setting(data, "#display-settings-status"); }); + $("#default_view").on("change", function () { + const data = {default_view: JSON.stringify(this.value)}; + change_display_setting(data, "#display-settings-status"); + }); + $("body").on("click", ".reload_link", () => { window.location.reload(); }); @@ -179,6 +186,7 @@ export function update_page() { $("#translate_emoticons").prop("checked", page_params.translate_emoticons); $("#twenty_four_hour_time").val(JSON.stringify(page_params.twenty_four_hour_time)); $("#color_scheme").val(JSON.stringify(page_params.color_scheme)); + $("#default_view").val(page_params.default_view); // TODO: Set emojiset selector here. // Longer term, we'll want to automate this function diff --git a/static/templates/settings/display_settings.hbs b/static/templates/settings/display_settings.hbs index 2cca09ebef..0a90eea539 100644 --- a/static/templates/settings/display_settings.hbs +++ b/static/templates/settings/display_settings.hbs @@ -21,6 +21,15 @@

{{t "Display settings" }}

+
+ + +
+
diff --git a/templates/zerver/api/changelog.md b/templates/zerver/api/changelog.md index f6ca084132..fa4c28e33f 100644 --- a/templates/zerver/api/changelog.md +++ b/templates/zerver/api/changelog.md @@ -10,14 +10,19 @@ below features are supported. ## Changes in Zulip 4.0 +**Feature level 42** + +* `PATCH /settings/display`: Added a new `default_view` setting allowing + the user to [set the default view](/help/change-default-view). + **Feature level 41** -* [`GET /events`](/api/get-events): Remove name field from update +* [`GET /events`](/api/get-events): Removed `name` field from update subscription events. **Feature level 40** -* [`GET /events`](/api/get-events): Remove email field from update +* [`GET /events`](/api/get-events): Removed `email` field from update subscription events. **Feature level 39** diff --git a/templates/zerver/app/keyboard_shortcuts.html b/templates/zerver/app/keyboard_shortcuts.html index f2b1885148..563ed94680 100644 --- a/templates/zerver/app/keyboard_shortcuts.html +++ b/templates/zerver/app/keyboard_shortcuts.html @@ -52,6 +52,10 @@ {% trans %}Show keyboard shortcuts{% endtrans %} ? + + {% trans %}Go to default view{% endtrans %} + Esc or Ctrl + [ +
@@ -241,7 +245,7 @@ {% trans %}View recent topics{% endtrans %} - T or Esc or Ctrl + [ + T {% trans %}Search recent topics{% endtrans %} diff --git a/templates/zerver/app/left_sidebar.html b/templates/zerver/app/left_sidebar.html index ef55ff9ef0..199edfc9fe 100644 --- a/templates/zerver/app/left_sidebar.html +++ b/templates/zerver/app/left_sidebar.html @@ -57,7 +57,7 @@
  • - + diff --git a/templates/zerver/help/change-default-view.md b/templates/zerver/help/change-default-view.md new file mode 100644 index 0000000000..cb6f72deba --- /dev/null +++ b/templates/zerver/help/change-default-view.md @@ -0,0 +1,26 @@ +# Change default view + +The default view in Zulip (i.e. what view you reach after logging in +to the Zulip webapp or hitting the `Esc` keyboard shortcut repeatedly) +can be configured. By default, **Recent topics** is the default view; +the previous default, **All messages**, is also supported. + +[Contact us](/help/contact-support) if you'd like to be able to +configure a different view as the default. + +### Change default view + +{start_tabs} + +{settings_tab|display-settings} + +2. Under **Display Settings**, click on the **Default view** dropdown. + +3. Select a view. + +4. Open a new Zulip tab or press `Esc` twice (first to exit + "Settings", and again to return to the default view) to see your + changes in action. + +{end_tabs} + diff --git a/templates/zerver/help/include/sidebar_index.md b/templates/zerver/help/include/sidebar_index.md index 900c3170ec..43df40f886 100644 --- a/templates/zerver/help/include/sidebar_index.md +++ b/templates/zerver/help/include/sidebar_index.md @@ -14,6 +14,7 @@ * [Review your settings](/help/review-your-settings) * [Change your profile picture](/help/change-your-profile-picture) * [Change your language](/help/change-your-language) +* [Change default view](/help/change-default-view) * [Use 24-hour time](/help/change-the-time-format) * [Joining an organization](/help/join-a-zulip-organization) * [Switching between organizations](/help/switching-between-organizations) diff --git a/templates/zerver/help/keyboard-shortcuts.md b/templates/zerver/help/keyboard-shortcuts.md index 30cd989ca0..ade8419e60 100644 --- a/templates/zerver/help/keyboard-shortcuts.md +++ b/templates/zerver/help/keyboard-shortcuts.md @@ -41,6 +41,9 @@ below, and add more to your repertoire as needed. * **Toggle keyboard shortcuts view**: `?` +* **Go to default view**: Press `Esc` or `Ctrl + [` until you are in + the [default view](/help/change-default-view). + ## Navigation * **Search messages**: `/` or `Ctrl+k` @@ -139,9 +142,9 @@ title="thumbs up"/>**: `+` ## Recent topics -* **View recent topics**: `t` or `Esc` or `Ctrl` + `[` +* **View recent topics**: `t` * **Search recent topics**: `t` -* **Escape from recent topics search**: `esc` or arrow keys +* **Escape from recent topics search**: `Esc` or arrow keys * **Navigate recent topics**: Use arrow keys or vim keys (`j`, `k`, `l`, `h`). Use `Enter` to engage with elements. diff --git a/version.py b/version.py index 3640520e64..b04a7e4c68 100644 --- a/version.py +++ b/version.py @@ -30,7 +30,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 = 41 +API_FEATURE_LEVEL = 42 # 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 @@ -45,4 +45,4 @@ API_FEATURE_LEVEL = 41 # historical commits sharing the same major version, in which case a # minor version bump suffices. -PROVISION_VERSION = "132.0" +PROVISION_VERSION = "133.0" diff --git a/zerver/migrations/0311_userprofile_default_view.py b/zerver/migrations/0311_userprofile_default_view.py new file mode 100644 index 0000000000..89182a8a74 --- /dev/null +++ b/zerver/migrations/0311_userprofile_default_view.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.7 on 2021-03-10 04:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("zerver", "0310_jsonfield"), + ] + + operations = [ + migrations.AddField( + model_name="userprofile", + name="default_view", + field=models.TextField(default="recent_topics"), + ), + ] diff --git a/zerver/models.py b/zerver/models.py index 72326706f6..b472caf208 100644 --- a/zerver/models.py +++ b/zerver/models.py @@ -1153,6 +1153,9 @@ class UserProfile(AbstractBaseUser, PermissionsMixin): # display settings default_language: str = models.CharField(default="en", max_length=MAX_LANGUAGE_ID_LENGTH) + # This setting controls which view is rendered first when Zulip loads. + # Values for it are URL suffix after `#`. + default_view: str = models.TextField(default="recent_topics") dense_mode: bool = models.BooleanField(default=True) fluid_layout_width: bool = models.BooleanField(default=False) high_contrast_mode: bool = models.BooleanField(default=False) @@ -1244,6 +1247,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin): property_types = dict( color_scheme=int, default_language=str, + default_view=str, demote_inactive_streams=int, dense_mode=bool, emojiset=str, diff --git a/zerver/openapi/zulip.yaml b/zerver/openapi/zulip.yaml index bc406e995f..09fc9094d4 100644 --- a/zerver/openapi/zulip.yaml +++ b/zerver/openapi/zulip.yaml @@ -6725,6 +6725,15 @@ paths: Present if `update_display_settings` is present in `fetch_event_types`. Whether the user has chosen for the layout width to be fluid. + default_view: + type: string + description: | + Present if `update_display_settings` is present in `fetch_event_types`. + + The [default view](/help/change-default-view) in Zulip, represented + as the URL suffix after `#` to be rendered when Zulip loads. + + Currently supported values are `all_messages` and `recent_topics`. high_contrast_mode: type: boolean description: | diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py index dfecda37ec..9ef59c2d50 100644 --- a/zerver/tests/test_events.py +++ b/zerver/tests/test_events.py @@ -1863,6 +1863,7 @@ class UserDisplayActionTest(BaseAction): test_changes: Dict[str, Any] = dict( emojiset=["twitter"], default_language=["es", "de", "en"], + default_view=["all_messages", "recent_topics"], timezone=["America/Denver", "Pacific/Pago_Pago", "Pacific/Galapagos", ""], demote_inactive_streams=[2, 3, 1], color_scheme=[2, 3, 1], diff --git a/zerver/tests/test_home.py b/zerver/tests/test_home.py index 4c063428c7..461450ecdf 100644 --- a/zerver/tests/test_home.py +++ b/zerver/tests/test_home.py @@ -53,6 +53,7 @@ class HomeTest(ZulipTestCase): "debug_mode", "default_language", "default_language_name", + "default_view", "delivery_email", "demote_inactive_streams", "dense_mode", diff --git a/zerver/tests/test_settings.py b/zerver/tests/test_settings.py index 9d4801d76b..4f8b78af3d 100644 --- a/zerver/tests/test_settings.py +++ b/zerver/tests/test_settings.py @@ -336,6 +336,7 @@ class ChangeSettingsTest(ZulipTestCase): test_changes: Dict[str, Any] = dict( default_language="de", + default_view="all_messages", emojiset="google", timezone="US/Mountain", demote_inactive_streams=2, diff --git a/zerver/tests/test_users.py b/zerver/tests/test_users.py index 37282388d4..e60ba27c83 100644 --- a/zerver/tests/test_users.py +++ b/zerver/tests/test_users.py @@ -1183,6 +1183,7 @@ class UserProfileTest(ZulipTestCase): hamlet.color_scheme = UserProfile.COLOR_SCHEME_LIGHT cordelia.default_language = "de" + cordelia.default_view = "all_messages" cordelia.emojiset = "twitter" cordelia.timezone = "America/Phoenix" cordelia.color_scheme = UserProfile.COLOR_SCHEME_NIGHT diff --git a/zerver/views/user_settings.py b/zerver/views/user_settings.py index 665e7f0e93..ae15e90de7 100644 --- a/zerver/views/user_settings.py +++ b/zerver/views/user_settings.py @@ -180,6 +180,7 @@ def json_change_settings( emojiset_choices = {emojiset["key"] for emojiset in UserProfile.emojiset_choices()} +default_view_options = ["recent_topics", "all_messages"] @human_users_only @@ -197,6 +198,9 @@ def update_display_settings_backend( ), translate_emoticons: Optional[bool] = REQ(validator=check_bool, default=None), default_language: Optional[str] = REQ(validator=check_string, default=None), + default_view: Optional[str] = REQ( + validator=check_string_in(default_view_options), default=None + ), left_side_userlist: Optional[bool] = REQ(validator=check_bool, default=None), emojiset: Optional[str] = REQ(validator=check_string_in(emojiset_choices), default=None), demote_inactive_streams: Optional[int] = REQ(