narrow: Save blue box position and restore on navigation.

This saves the blue box position as state on the location
in brower history, with `history.replaceState`.

The position is restored when a narrow is activated.

Fixes #20066.
This commit is contained in:
evykassirer 2023-08-08 14:59:25 -07:00 committed by Tim Abbott
parent 5a8416ff6a
commit 78f0dca269
6 changed files with 57 additions and 0 deletions

View File

@ -126,6 +126,7 @@ EXEMPT_FILES = make_set(
"web/src/messages_overlay_ui.ts",
"web/src/muted_users_ui.js",
"web/src/narrow.js",
"web/src/narrow_history.js",
"web/src/navbar_alerts.js",
"web/src/navigate.js",
"web/src/notifications.js",

View File

@ -200,6 +200,12 @@ function do_hashchange_normal(from_reload) {
narrow_opts.then_select_offset = page_params.initial_narrow_offset;
}
}
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;
}
narrow.activate(operators, narrow_opts);
return true;
}

View File

@ -27,6 +27,7 @@ import * as message_lists from "./message_lists";
import * as message_store from "./message_store";
import * as message_view_header from "./message_view_header";
import * as narrow_banner from "./narrow_banner";
import * as narrow_history from "./narrow_history";
import * as narrow_state from "./narrow_state";
import * as notifications from "./notifications";
import {page_params} from "./page_params";
@ -792,6 +793,7 @@ export function update_selection(opts) {
message_lists.current.view.set_message_offset(select_offset);
}
unread_ops.process_visible();
narrow_history.save_narrow_state_and_flush();
}
export function activate_stream_for_cycle_hotkey(stream_name) {

43
web/src/narrow_history.js Normal file
View File

@ -0,0 +1,43 @@
import _ from "lodash";
import * as hash_util from "./hash_util";
import * as message_lists from "./message_lists";
import * as narrow_state from "./narrow_state";
// Saves the selected message of the narrow in the browser
// history, so that we are able to restore it if the user
// navigates back to this page.
function _save_narrow_state() {
if (!narrow_state.active()) {
return;
}
// We don't want to save state in the middle of a narrow change
// to the wrong hash.
const current_filter = message_lists.current.data.filter;
if (hash_util.operators_to_hash(current_filter.operators()) !== window.location.hash) {
return;
}
const narrow_data = {};
const narrow_pointer = message_lists.current.selected_id();
if (narrow_pointer === -1) {
return;
}
narrow_data.narrow_pointer = narrow_pointer;
const $narrow_row = message_lists.current.selected_row();
if ($narrow_row.length === 0) {
return;
}
narrow_data.narrow_offset = $narrow_row.get_offset_to_window().top;
history.replaceState(narrow_data, "", window.location.href);
}
// Safari limits you to 100 replaceState calls in 30 seconds.
export const save_narrow_state = _.throttle(_save_narrow_state, 500);
// This causes the save to happen right away.
export function save_narrow_state_and_flush() {
save_narrow_state();
save_narrow_state.flush();
}

View File

@ -58,6 +58,7 @@ import * as message_view_header from "./message_view_header";
import * as message_viewport from "./message_viewport";
import * as muted_users from "./muted_users";
import * as narrow from "./narrow";
import * as narrow_history from "./narrow_history";
import * as narrow_state from "./narrow_state";
import * as navbar_alerts from "./navbar_alerts";
import * as navigate from "./navigate";
@ -400,6 +401,7 @@ export function initialize_kitchen_sink_stuff() {
const $row = event.msg_list.get_row(event.id);
$(".selected_message").removeClass("selected_message");
$row.addClass("selected_message");
narrow_history.save_narrow_state();
if (event.then_scroll) {
if ($row.length === 0) {

View File

@ -28,6 +28,7 @@ const message_lists = mock_esm("../src/message_lists", {
const message_feed_top_notices = mock_esm("../src/message_feed_top_notices");
const message_feed_loading = mock_esm("../src/message_feed_loading");
const message_view_header = mock_esm("../src/message_view_header");
const narrow_history = mock_esm("../src/narrow_history");
const notifications = mock_esm("../src/notifications");
const stream_list = mock_esm("../src/stream_list");
const left_sidebar_navigation_area = mock_esm("../src/left_sidebar_navigation_area");
@ -81,6 +82,7 @@ function test_helper({override}) {
stub(compose_banner, "clear_message_sent_banners");
stub(compose_actions, "on_narrow");
stub(compose_closed_ui, "update_reply_recipient_label");
stub(narrow_history, "save_narrow_state_and_flush");
stub(hashchange, "save_narrow");
stub(message_feed_loading, "hide_indicators");
stub(message_feed_top_notices, "hide_top_of_narrow_notices");
@ -186,6 +188,7 @@ run_test("basics", ({override}) => {
[compose_banner, "clear_message_sent_banners"],
[notifications, "redraw_title"],
[unread_ops, "process_visible"],
[narrow_history, "save_narrow_state_and_flush"],
[hashchange, "save_narrow"],
[compose_closed_ui, "update_buttons_for_stream"],
[compose_closed_ui, "update_reply_recipient_label"],