mirror of
https://github.com/zulip/zulip.git
synced 2025-11-05 06:23:38 +00:00
recent_topics: Don't rely on ":visible" to avoid forced reflow.
Previously, navigating from any stream to the recent topics view would
cause a forced reflow every time we checked `is_visible()` because it
would call `$("#recent_topics_view").is(":visible")`.
The reason for this is related to how browsers ship frames, the
process follows these steps:
JavaScript > style calculations > layout > paint > composite.
(The layout step is called Reflow in firefox.)
Typically, the browser will handle these steps in the most optimal
manner possible, delaying expensive operations until they're needed.
However, it is possible to cause the browser to perform a layout
earlier than necessary. An example of this is what we previously did:
When we call `top_left_corner.narrow_to_recent_topics()`, we ask to
add a class via `.addClass()`, this schedules a Style Recalculation,
then, when we call `message_view_header.make_message_view_header()` it
calls `recent_topics_util.is_visible()` which calls
`$("#recent_topics_view").is(":visible")`.
Before the browser can get this value, it realizes that our dom was
invalidated by `.addClass()` and so it must execute the scheduled
Style Recalculation and cause a layout.
This is called a forced synchronous layout.
This commit adds a JavaScript variable representing the visible state,
in order to prevent the above behavior.
This commit reduces the main thread run time of
`build_message_view_header` from 131.81 ms to 5.20 ms.
Unfortunately we still have the case where
`recent_topics_ui.revive_current_focus()` calls
`recent_topics_ui.set_table_focus()` which causes a reflow.
However, by eliminating this reflow we still save ~100ms.
(It's important to note that we only save this sometimes, as other
things can still cost us a reflow.)
Further reading: https://developers.google.com/web/fundamentals/
performance/rendering/avoid-large-complex-layouts-and-layout-thrashing
This commit is contained in:
@@ -20,7 +20,7 @@ import * as navigate from "./navigate";
|
||||
import * as people from "./people";
|
||||
import * as recent_senders from "./recent_senders";
|
||||
import {get, process_message, topics} from "./recent_topics_data";
|
||||
import {get_topic_key, is_in_focus, is_visible} from "./recent_topics_util";
|
||||
import {get_topic_key, is_in_focus, is_visible, set_visible} from "./recent_topics_util";
|
||||
import * as stream_data from "./stream_data";
|
||||
import * as stream_list from "./stream_list";
|
||||
import * as sub_store from "./sub_store";
|
||||
@@ -600,6 +600,7 @@ export function show() {
|
||||
// a messages narrow. We hide it and show recent topics.
|
||||
$("#message_feed_container").hide();
|
||||
$("#recent_topics_view").show();
|
||||
set_visible(true);
|
||||
$("#message_view_header_underpadding").hide();
|
||||
$(".header").css("padding-bottom", "0px");
|
||||
|
||||
@@ -622,6 +623,7 @@ function filter_buttons() {
|
||||
export function hide() {
|
||||
$("#message_feed_container").show();
|
||||
$("#recent_topics_view").hide();
|
||||
set_visible(false);
|
||||
// On firefox (and flaky on other browsers), focus
|
||||
// remains on search box even after it is hidden. We
|
||||
// forcefully blur it so that focus returns to the visible
|
||||
|
||||
@@ -4,8 +4,14 @@ import * as compose_state from "./compose_state";
|
||||
import * as overlays from "./overlays";
|
||||
import * as popovers from "./popovers";
|
||||
|
||||
let is_rt_visible = false;
|
||||
|
||||
export function set_visible(value) {
|
||||
is_rt_visible = value;
|
||||
}
|
||||
|
||||
export function is_visible() {
|
||||
return $("#recent_topics_view").is(":visible");
|
||||
return is_rt_visible;
|
||||
}
|
||||
|
||||
export function is_in_focus() {
|
||||
|
||||
Reference in New Issue
Block a user