From 95be5db08b605be5eba9362da46334d272c71bd7 Mon Sep 17 00:00:00 2001 From: Prakhar Pratyush Date: Tue, 30 Apr 2024 19:58:32 +0530 Subject: [PATCH] narrow: Add 'more topics' state to browser history. When navigating "back" or "forward", the left sidebar state should be restored. Earlier, "more topics" expanded was not considered a distinct state. This commit makes it possible to correctly place you in the "more topics" view or not, depending on where you were. Fixes #29548. --- web/src/browser_history.ts | 18 ++++++++++++++++++ web/src/hashchange.js | 10 ++++++---- web/src/narrow.js | 12 +++++++++--- web/src/narrow_history.ts | 2 +- web/src/stream_list.ts | 16 +++++++++++++++- web/tests/narrow_activate.test.js | 3 ++- 6 files changed, 51 insertions(+), 10 deletions(-) diff --git a/web/src/browser_history.ts b/web/src/browser_history.ts index 23245d60de..fe86a34353 100644 --- a/web/src/browser_history.ts +++ b/web/src/browser_history.ts @@ -154,3 +154,21 @@ export function set_hash(hash: string): void { window.location.hash = hash; } } + +type StateData = { + narrow_pointer?: number; + narrow_offset?: number; + show_more_topics?: boolean; +}; + +export function update_current_history_state_data(new_data: StateData): void { + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + const current_state = history.state as StateData | null; + const current_state_data = { + narrow_pointer: current_state?.narrow_pointer, + narrow_offset: current_state?.narrow_offset, + show_more_topics: current_state?.show_more_topics, + }; + const state_data = {...current_state_data, ...new_data}; + history.replaceState(state_data, "", window.location.href); +} diff --git a/web/src/hashchange.js b/web/src/hashchange.js index 18c3458d96..8f619adda6 100644 --- a/web/src/hashchange.js +++ b/web/src/hashchange.js @@ -182,6 +182,7 @@ function do_hashchange_normal(from_reload) { const narrow_opts = { change_hash: false, // already set trigger: "hash change", + show_more_topics: false, }; if (from_reload) { blueslip.debug("We are narrowing as part of a reload."); @@ -191,10 +192,11 @@ function do_hashchange_normal(from_reload) { } } - const location_data_for_hash = history.state; - if (location_data_for_hash) { - narrow_opts.then_select_id = location_data_for_hash.narrow_pointer; - narrow_opts.then_select_offset = location_data_for_hash.narrow_offset; + const data_for_hash = history.state; + if (data_for_hash) { + narrow_opts.then_select_id = data_for_hash.narrow_pointer; + narrow_opts.then_select_offset = data_for_hash.narrow_offset; + narrow_opts.show_more_topics = data_for_hash.show_more_topics ?? false; } narrow.activate(terms, narrow_opts); return true; diff --git a/web/src/narrow.js b/web/src/narrow.js index 861f5e156e..be06041dd8 100644 --- a/web/src/narrow.js +++ b/web/src/narrow.js @@ -92,6 +92,10 @@ export function update_hash_to_match_filter(filter, trigger) { } const new_hash = hash_util.search_terms_to_hash(filter.terms()); changehash(new_hash, trigger); + + if (stream_list.is_zoomed_in()) { + browser_history.update_current_history_state_data({show_more_topics: true}); + } } function create_and_update_message_list(filter, id_info, opts) { @@ -166,6 +170,7 @@ function create_and_update_message_list(filter, id_info, opts) { // workflow we have which calls `narrow.activate` after hash is updated. if (opts.change_hash) { update_hash_to_match_filter(filter, opts.trigger); + opts.show_more_topics = history.state?.show_more_topics ?? false; } // Show the new set of messages. It is important to set message_lists.current to @@ -263,6 +268,7 @@ export function activate(raw_terms, opts) { then_select_offset: undefined, change_hash: true, trigger: "unknown", + show_more_topics: false, ...opts, }; @@ -606,7 +612,7 @@ export function activate(raw_terms, opts) { }); } - handle_post_view_change(msg_list); + handle_post_view_change(msg_list, opts); unread_ui.update_unread_banner(); @@ -1086,7 +1092,7 @@ export function to_compose_target() { } } -function handle_post_view_change(msg_list) { +function handle_post_view_change(msg_list, opts) { const filter = msg_list.data.filter; scheduled_messages_feed_ui.update_schedule_message_indicator(); typing_events.render_notifications_for_narrow(); @@ -1103,7 +1109,7 @@ function handle_post_view_change(msg_list) { message_view_header.render_title_area(); narrow_title.update_narrow_title(filter); left_sidebar_navigation_area.handle_narrow_activated(filter); - stream_list.handle_narrow_activated(filter); + stream_list.handle_narrow_activated(filter, opts.change_hash, opts.show_more_topics); pm_list.handle_narrow_activated(filter); activity_ui.build_user_sidebar(); } diff --git a/web/src/narrow_history.ts b/web/src/narrow_history.ts index 831eb4cb06..5a891b2760 100644 --- a/web/src/narrow_history.ts +++ b/web/src/narrow_history.ts @@ -34,7 +34,7 @@ function _save_narrow_state(): void { narrow_pointer, narrow_offset, }; - history.replaceState(narrow_data, "", window.location.href); + browser_history.update_current_history_state_data(narrow_data); } // Safari limits you to 100 replaceState calls in 30 seconds. diff --git a/web/src/stream_list.ts b/web/src/stream_list.ts index 5c97259521..77af1b8e1c 100644 --- a/web/src/stream_list.ts +++ b/web/src/stream_list.ts @@ -9,6 +9,7 @@ import render_stream_subheader from "../templates/streams_subheader.hbs"; import render_subscribe_to_more_streams from "../templates/subscribe_to_more_streams.hbs"; import * as blueslip from "./blueslip"; +import * as browser_history from "./browser_history"; import type {Filter} from "./filter"; import * as hash_util from "./hash_util"; import {$t} from "./i18n"; @@ -746,10 +747,21 @@ export function update_stream_sidebar_for_narrow(filter: Filter): JQuery | undef return $stream_li; } -export function handle_narrow_activated(filter: Filter): void { +export function handle_narrow_activated( + filter: Filter, + change_hash: boolean, + show_more_topics: boolean, +): void { const $stream_li = update_stream_sidebar_for_narrow(filter); if ($stream_li) { scroll_stream_into_view($stream_li); + if (!change_hash) { + if (!is_zoomed_in() && show_more_topics) { + zoom_in(); + } else if (is_zoomed_in() && !show_more_topics) { + zoom_out(); + } + } } } @@ -805,6 +817,7 @@ export function initialize({ $("#stream_filters").on("click", ".show-more-topics", (e) => { zoom_in(); + browser_history.update_current_history_state_data({show_more_topics: true}); e.preventDefault(); e.stopPropagation(); @@ -812,6 +825,7 @@ export function initialize({ $(".show-all-streams").on("click", (e) => { zoom_out(); + browser_history.update_current_history_state_data({show_more_topics: false}); e.preventDefault(); e.stopPropagation(); diff --git a/web/tests/narrow_activate.test.js b/web/tests/narrow_activate.test.js index e2ada83112..d727a484ea 100644 --- a/web/tests/narrow_activate.test.js +++ b/web/tests/narrow_activate.test.js @@ -6,6 +6,7 @@ const {mock_esm, set_global, zrequire} = require("./lib/namespace"); const {run_test, noop} = require("./lib/test"); const $ = require("./lib/zjquery"); +set_global("history", {}); mock_esm("../src/resize", { resize_stream_filters_container() {}, }); @@ -46,7 +47,7 @@ const message_view_header = mock_esm("../src/message_view_header"); const message_viewport = mock_esm("../src/message_viewport"); const narrow_history = mock_esm("../src/narrow_history"); const narrow_title = mock_esm("../src/narrow_title"); -const stream_list = mock_esm("../src/stream_list"); +const stream_list = mock_esm("../src/stream_list", {is_zoomed_in: () => false}); const left_sidebar_navigation_area = mock_esm("../src/left_sidebar_navigation_area"); const typing_events = mock_esm("../src/typing_events"); const unread_ops = mock_esm("../src/unread_ops");