mirror of https://github.com/zulip/zulip.git
ts: Migrate `message_viewport` to typescript.
Used function overloading for methods - `make_dimen_wrapper` and `scrollTop`.
This commit is contained in:
parent
f2c700b6e1
commit
6f6795f607
|
@ -144,7 +144,7 @@ EXEMPT_FILES = make_set(
|
||||||
"web/src/message_scroll_state.ts",
|
"web/src/message_scroll_state.ts",
|
||||||
"web/src/message_util.ts",
|
"web/src/message_util.ts",
|
||||||
"web/src/message_view_header.js",
|
"web/src/message_view_header.js",
|
||||||
"web/src/message_viewport.js",
|
"web/src/message_viewport.ts",
|
||||||
"web/src/messages_overlay_ui.ts",
|
"web/src/messages_overlay_ui.ts",
|
||||||
"web/src/modals.ts",
|
"web/src/modals.ts",
|
||||||
"web/src/muted_users_ui.js",
|
"web/src/muted_users_ui.js",
|
||||||
|
|
|
@ -1,30 +1,54 @@
|
||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
|
import assert from "minimalistic-assert";
|
||||||
|
|
||||||
import * as blueslip from "./blueslip";
|
import * as blueslip from "./blueslip";
|
||||||
import * as message_lists from "./message_lists";
|
import * as message_lists from "./message_lists";
|
||||||
import * as message_scroll_state from "./message_scroll_state";
|
import * as message_scroll_state from "./message_scroll_state";
|
||||||
|
import type {Message} from "./message_store";
|
||||||
import * as rows from "./rows";
|
import * as rows from "./rows";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
|
import type {CachedValue} from "./util";
|
||||||
|
|
||||||
|
type MessageViewportInfo = {
|
||||||
|
visible_top: number;
|
||||||
|
visible_bottom: number;
|
||||||
|
visible_height: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type DimenFunc = JQuery["height"] | JQuery["width"];
|
||||||
|
type DimenWrapper = {
|
||||||
|
(): number;
|
||||||
|
(val: string | number): JQuery;
|
||||||
|
};
|
||||||
|
|
||||||
export const $scroll_container = $("html");
|
export const $scroll_container = $("html");
|
||||||
|
|
||||||
let $jwindow;
|
let $jwindow: JQuery<Window & typeof globalThis>;
|
||||||
const dimensions = {};
|
const dimensions: Record<string, CachedValue<number>> = {};
|
||||||
let in_stoppable_autoscroll = false;
|
let in_stoppable_autoscroll = false;
|
||||||
|
|
||||||
function make_dimen_wrapper(dimen_name, dimen_func) {
|
function make_dimen_wrapper(dimen_name: string, dimen_func: DimenFunc): DimenWrapper {
|
||||||
dimensions[dimen_name] = new util.CachedValue({
|
dimensions[dimen_name] = new util.CachedValue({
|
||||||
compute_value() {
|
compute_value() {
|
||||||
return dimen_func();
|
return dimen_func() ?? 0;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return function viewport_dimension_wrapper(val) {
|
|
||||||
|
// Inner function overload for the case when dimen_func is () => number | undefined
|
||||||
|
function viewport_dimension_wrapper(): number;
|
||||||
|
|
||||||
|
// Inner function overload for the case when dimen_func is (val: string | number) => JQuery
|
||||||
|
function viewport_dimension_wrapper(val: string | number): JQuery;
|
||||||
|
|
||||||
|
function viewport_dimension_wrapper(val?: string | number): number | JQuery {
|
||||||
if (val !== undefined) {
|
if (val !== undefined) {
|
||||||
dimensions[dimen_name].reset();
|
dimensions[dimen_name].reset();
|
||||||
return dimen_func(val);
|
return dimen_func(val);
|
||||||
}
|
}
|
||||||
return dimensions[dimen_name].get();
|
return dimensions[dimen_name].get();
|
||||||
};
|
}
|
||||||
|
|
||||||
|
return viewport_dimension_wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const height = make_dimen_wrapper("height", $.fn.height.bind($scroll_container));
|
export const height = make_dimen_wrapper("height", $.fn.height.bind($scroll_container));
|
||||||
|
@ -33,23 +57,23 @@ export const width = make_dimen_wrapper("width", $.fn.width.bind($scroll_contain
|
||||||
// TODO: This function lets us use the DOM API instead of jquery
|
// TODO: This function lets us use the DOM API instead of jquery
|
||||||
// (<10x faster) for condense.js, but we want to eventually do a
|
// (<10x faster) for condense.js, but we want to eventually do a
|
||||||
// bigger of refactor `height` and `width` above to do the same.
|
// bigger of refactor `height` and `width` above to do the same.
|
||||||
export function max_message_height() {
|
export function max_message_height(): number {
|
||||||
return document.querySelector("html").offsetHeight * 0.65;
|
return document.querySelector("html")!.offsetHeight * 0.65;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Includes both scroll and arrow events. Negative means scroll up,
|
// Includes both scroll and arrow events. Negative means scroll up,
|
||||||
// positive means scroll down.
|
// positive means scroll down.
|
||||||
export let last_movement_direction = 1;
|
export let last_movement_direction = 1;
|
||||||
|
|
||||||
export function set_last_movement_direction(value) {
|
export function set_last_movement_direction(value: number): void {
|
||||||
last_movement_direction = value;
|
last_movement_direction = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function at_top() {
|
export function at_top(): boolean {
|
||||||
return scrollTop() <= 0;
|
return scrollTop() <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function message_viewport_info() {
|
export function message_viewport_info(): MessageViewportInfo {
|
||||||
// Return a structure that tells us details of the viewport
|
// Return a structure that tells us details of the viewport
|
||||||
// accounting for fixed elements like the top navbar.
|
// accounting for fixed elements like the top navbar.
|
||||||
//
|
//
|
||||||
|
@ -78,7 +102,7 @@ export function message_viewport_info() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function at_bottom() {
|
export function at_bottom(): boolean {
|
||||||
const bottom = scrollTop() + height();
|
const bottom = scrollTop() + height();
|
||||||
const full_height = $scroll_container.prop("scrollHeight");
|
const full_height = $scroll_container.prop("scrollHeight");
|
||||||
|
|
||||||
|
@ -91,7 +115,7 @@ export function at_bottom() {
|
||||||
|
|
||||||
// This differs from at_bottom in that it only requires the bottom message to
|
// This differs from at_bottom in that it only requires the bottom message to
|
||||||
// be visible, but you may be able to scroll down further.
|
// be visible, but you may be able to scroll down further.
|
||||||
export function bottom_message_visible() {
|
export function bottom_message_visible(): boolean {
|
||||||
const $last_row = rows.last_visible();
|
const $last_row = rows.last_visible();
|
||||||
if ($last_row.length) {
|
if ($last_row.length) {
|
||||||
const message_bottom = $last_row[0].getBoundingClientRect().bottom;
|
const message_bottom = $last_row[0].getBoundingClientRect().bottom;
|
||||||
|
@ -101,11 +125,11 @@ export function bottom_message_visible() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function is_below_visible_bottom(offset) {
|
export function is_below_visible_bottom(offset: number): boolean {
|
||||||
return offset > scrollTop() + height() - $("#compose").height();
|
return offset > scrollTop() + height() - ($("#compose").height() ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function is_scrolled_up() {
|
export function is_scrolled_up(): boolean {
|
||||||
// Let's determine whether the user was already dealing
|
// Let's determine whether the user was already dealing
|
||||||
// with messages off the screen, which can guide auto
|
// with messages off the screen, which can guide auto
|
||||||
// scrolling decisions.
|
// scrolling decisions.
|
||||||
|
@ -119,7 +143,7 @@ export function is_scrolled_up() {
|
||||||
return offset > 0;
|
return offset > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function offset_from_bottom($last_row) {
|
export function offset_from_bottom($last_row: JQuery): number {
|
||||||
// A positive return value here means the last row is
|
// A positive return value here means the last row is
|
||||||
// below the bottom of the feed (i.e. obscured by the compose
|
// below the bottom of the feed (i.e. obscured by the compose
|
||||||
// box or even further below the bottom).
|
// box or even further below the bottom).
|
||||||
|
@ -129,7 +153,12 @@ export function offset_from_bottom($last_row) {
|
||||||
return message_bottom - info.visible_bottom;
|
return message_bottom - info.visible_bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function set_message_position(message_top, message_height, viewport_info, ratio) {
|
export function set_message_position(
|
||||||
|
message_top: number,
|
||||||
|
message_height: number,
|
||||||
|
viewport_info: MessageViewportInfo,
|
||||||
|
ratio: number,
|
||||||
|
): void {
|
||||||
// message_top = offset of the top of a message that you are positioning
|
// message_top = offset of the top of a message that you are positioning
|
||||||
// message_height = height of the message that you are positioning
|
// message_height = height of the message that you are positioning
|
||||||
// viewport_info = result of calling message_viewport.message_viewport_info
|
// viewport_info = result of calling message_viewport.message_viewport_info
|
||||||
|
@ -160,7 +189,12 @@ export function set_message_position(message_top, message_height, viewport_info,
|
||||||
scrollTop(new_scroll_top);
|
scrollTop(new_scroll_top);
|
||||||
}
|
}
|
||||||
|
|
||||||
function in_viewport_or_tall(rect, top_of_feed, bottom_of_feed, require_fully_visible) {
|
function in_viewport_or_tall(
|
||||||
|
rect: DOMRect,
|
||||||
|
top_of_feed: number,
|
||||||
|
bottom_of_feed: number,
|
||||||
|
require_fully_visible: boolean,
|
||||||
|
): boolean {
|
||||||
if (require_fully_visible) {
|
if (require_fully_visible) {
|
||||||
return (
|
return (
|
||||||
rect.top > top_of_feed && // Message top is in view and
|
rect.top > top_of_feed && // Message top is in view and
|
||||||
|
@ -171,14 +205,14 @@ function in_viewport_or_tall(rect, top_of_feed, bottom_of_feed, require_fully_vi
|
||||||
return rect.bottom > top_of_feed && rect.top < bottom_of_feed;
|
return rect.bottom > top_of_feed && rect.top < bottom_of_feed;
|
||||||
}
|
}
|
||||||
|
|
||||||
function add_to_visible(
|
function add_to_visible<T>(
|
||||||
$candidates,
|
$candidates: JQuery,
|
||||||
visible,
|
visible: T[],
|
||||||
top_of_feed,
|
top_of_feed: number,
|
||||||
bottom_of_feed,
|
bottom_of_feed: number,
|
||||||
require_fully_visible,
|
require_fully_visible: boolean,
|
||||||
row_to_id,
|
row_to_id: ($row: HTMLElement) => T,
|
||||||
) {
|
): void {
|
||||||
for (const row of $candidates) {
|
for (const row of $candidates) {
|
||||||
const row_rect = row.getBoundingClientRect();
|
const row_rect = row.getBoundingClientRect();
|
||||||
// Mark very tall messages as read once we've gotten past them
|
// Mark very tall messages as read once we've gotten past them
|
||||||
|
@ -209,13 +243,13 @@ const bottom_of_feed = new util.CachedValue({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function _visible_divs(
|
function _visible_divs<T>(
|
||||||
$selected_row,
|
$selected_row: JQuery,
|
||||||
row_min_height,
|
row_min_height: number,
|
||||||
row_to_output,
|
row_to_output: ($row: HTMLElement) => T,
|
||||||
div_class,
|
div_class: string,
|
||||||
require_fully_visible,
|
require_fully_visible: boolean,
|
||||||
) {
|
): T[] {
|
||||||
// Note that when using getBoundingClientRect() we are getting offsets
|
// Note that when using getBoundingClientRect() we are getting offsets
|
||||||
// relative to the visible window, but when using jQuery's offset() we are
|
// relative to the visible window, but when using jQuery's offset() we are
|
||||||
// getting offsets relative to the full scrollable window. You can't try to
|
// getting offsets relative to the full scrollable window. You can't try to
|
||||||
|
@ -225,7 +259,7 @@ function _visible_divs(
|
||||||
|
|
||||||
// We do this explicitly without merges and without recalculating
|
// We do this explicitly without merges and without recalculating
|
||||||
// the feed bounds to keep this computation as cheap as possible.
|
// the feed bounds to keep this computation as cheap as possible.
|
||||||
const visible = [];
|
const visible: T[] = [];
|
||||||
const $above_pointer = $selected_row
|
const $above_pointer = $selected_row
|
||||||
.prevAll(`div.${CSS.escape(div_class)}`)
|
.prevAll(`div.${CSS.escape(div_class)}`)
|
||||||
.slice(0, num_neighbors);
|
.slice(0, num_neighbors);
|
||||||
|
@ -260,7 +294,8 @@ function _visible_divs(
|
||||||
return visible;
|
return visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function visible_groups(require_fully_visible) {
|
export function visible_groups(require_fully_visible: boolean): HTMLElement[] {
|
||||||
|
assert(message_lists.current !== undefined);
|
||||||
const $selected_row = message_lists.current.selected_row();
|
const $selected_row = message_lists.current.selected_row();
|
||||||
if ($selected_row === undefined || $selected_row.length === 0) {
|
if ($selected_row === undefined || $selected_row.length === 0) {
|
||||||
return [];
|
return [];
|
||||||
|
@ -268,29 +303,45 @@ export function visible_groups(require_fully_visible) {
|
||||||
|
|
||||||
const $selected_group = rows.get_message_recipient_row($selected_row);
|
const $selected_group = rows.get_message_recipient_row($selected_row);
|
||||||
|
|
||||||
function get_row(row) {
|
function get_row(row: HTMLElement): HTMLElement {
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Being simplistic about this, the smallest group is about 75 px high.
|
// Being simplistic about this, the smallest group is about 75 px high.
|
||||||
return _visible_divs($selected_group, 75, get_row, "recipient_row", require_fully_visible);
|
return _visible_divs<HTMLElement>(
|
||||||
|
$selected_group,
|
||||||
|
75,
|
||||||
|
get_row,
|
||||||
|
"recipient_row",
|
||||||
|
require_fully_visible,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function visible_messages(require_fully_visible) {
|
export function visible_messages(require_fully_visible: boolean): Message[] {
|
||||||
|
assert(message_lists.current !== undefined);
|
||||||
const $selected_row = message_lists.current.selected_row();
|
const $selected_row = message_lists.current.selected_row();
|
||||||
|
|
||||||
function row_to_id(row) {
|
function row_to_id(row: HTMLElement): Message {
|
||||||
return message_lists.current.get(rows.id($(row)));
|
assert(message_lists.current !== undefined);
|
||||||
|
return message_lists.current.get(rows.id($(row))!)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Being simplistic about this, the smallest message is 25 px high.
|
// Being simplistic about this, the smallest message is 25 px high.
|
||||||
return _visible_divs($selected_row, 25, row_to_id, "message_row", require_fully_visible);
|
return _visible_divs<Message>(
|
||||||
|
$selected_row,
|
||||||
|
25,
|
||||||
|
row_to_id,
|
||||||
|
"message_row",
|
||||||
|
require_fully_visible,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function scrollTop(target_scrollTop) {
|
export function scrollTop(): number;
|
||||||
|
export function scrollTop(target_scrollTop: number): JQuery;
|
||||||
|
export function scrollTop(target_scrollTop?: number): JQuery | number {
|
||||||
const orig_scrollTop = $scroll_container.scrollTop();
|
const orig_scrollTop = $scroll_container.scrollTop();
|
||||||
if (target_scrollTop === undefined) {
|
if (target_scrollTop === undefined) {
|
||||||
return orig_scrollTop;
|
return orig_scrollTop ?? 0;
|
||||||
}
|
}
|
||||||
let $ret = $scroll_container.scrollTop(target_scrollTop);
|
let $ret = $scroll_container.scrollTop(target_scrollTop);
|
||||||
const new_scrollTop = $scroll_container.scrollTop();
|
const new_scrollTop = $scroll_container.scrollTop();
|
||||||
|
@ -327,13 +378,13 @@ export function scrollTop(target_scrollTop) {
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stop_auto_scrolling() {
|
export function stop_auto_scrolling(): void {
|
||||||
if (in_stoppable_autoscroll) {
|
if (in_stoppable_autoscroll) {
|
||||||
$scroll_container.stop();
|
$scroll_container.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function system_initiated_animate_scroll(scroll_amount) {
|
export function system_initiated_animate_scroll(scroll_amount: number): void {
|
||||||
message_scroll_state.set_update_selection_on_next_scroll(false);
|
message_scroll_state.set_update_selection_on_next_scroll(false);
|
||||||
const viewport_offset = scrollTop();
|
const viewport_offset = scrollTop();
|
||||||
in_stoppable_autoscroll = true;
|
in_stoppable_autoscroll = true;
|
||||||
|
@ -345,7 +396,7 @@ export function system_initiated_animate_scroll(scroll_amount) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function user_initiated_animate_scroll(scroll_amount) {
|
export function user_initiated_animate_scroll(scroll_amount: number): void {
|
||||||
message_scroll_state.set_update_selection_on_next_scroll(false);
|
message_scroll_state.set_update_selection_on_next_scroll(false);
|
||||||
in_stoppable_autoscroll = false; // defensive
|
in_stoppable_autoscroll = false; // defensive
|
||||||
|
|
||||||
|
@ -356,7 +407,10 @@ export function user_initiated_animate_scroll(scroll_amount) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function recenter_view($message, {from_scroll = false, force_center = false} = {}) {
|
export function recenter_view(
|
||||||
|
$message: JQuery,
|
||||||
|
{from_scroll = false, force_center = false} = {},
|
||||||
|
): void {
|
||||||
// BarnOwl-style recentering: if the pointer is too high, move it to
|
// BarnOwl-style recentering: if the pointer is too high, move it to
|
||||||
// the 1/2 marks. If the pointer is too low, move it to the 1/7 mark.
|
// the 1/2 marks. If the pointer is too low, move it to the 1/7 mark.
|
||||||
// See keep_pointer_in_view() for related logic to keep the pointer onscreen.
|
// See keep_pointer_in_view() for related logic to keep the pointer onscreen.
|
||||||
|
@ -394,7 +448,8 @@ export function recenter_view($message, {from_scroll = false, force_center = fal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function maybe_scroll_to_show_message_top() {
|
export function maybe_scroll_to_show_message_top(): void {
|
||||||
|
assert(message_lists.current !== undefined);
|
||||||
// Sets the top of the message to the top of the viewport.
|
// Sets the top of the message to the top of the viewport.
|
||||||
// Only applies if the top of the message is out of view above the visible area.
|
// Only applies if the top of the message is out of view above the visible area.
|
||||||
const $selected_message = message_lists.current.selected_row();
|
const $selected_message = message_lists.current.selected_row();
|
||||||
|
@ -406,13 +461,14 @@ export function maybe_scroll_to_show_message_top() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function is_message_below_viewport($message_row) {
|
export function is_message_below_viewport($message_row: JQuery): boolean {
|
||||||
const info = message_viewport_info();
|
const info = message_viewport_info();
|
||||||
const offset = $message_row.get_offset_to_window();
|
const offset = $message_row.get_offset_to_window();
|
||||||
return offset.top >= info.visible_bottom;
|
return offset.top >= info.visible_bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function keep_pointer_in_view() {
|
export function keep_pointer_in_view(): void {
|
||||||
|
assert(message_lists.current !== undefined);
|
||||||
// See message_viewport.recenter_view() for related logic to keep the pointer onscreen.
|
// See message_viewport.recenter_view() for related logic to keep the pointer onscreen.
|
||||||
// This function mostly comes into place for mouse scrollers, and it
|
// This function mostly comes into place for mouse scrollers, and it
|
||||||
// keeps the pointer in view. For people who purely scroll with the
|
// keeps the pointer in view. For people who purely scroll with the
|
||||||
|
@ -430,7 +486,7 @@ export function keep_pointer_in_view() {
|
||||||
const top_threshold = info.visible_top + (1 / 10) * info.visible_height;
|
const top_threshold = info.visible_top + (1 / 10) * info.visible_height;
|
||||||
const bottom_threshold = info.visible_top + (9 / 10) * info.visible_height;
|
const bottom_threshold = info.visible_top + (9 / 10) * info.visible_height;
|
||||||
|
|
||||||
function message_is_far_enough_down() {
|
function message_is_far_enough_down(): boolean {
|
||||||
if (at_top()) {
|
if (at_top()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -455,11 +511,14 @@ export function keep_pointer_in_view() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function message_is_far_enough_up() {
|
function message_is_far_enough_up(): boolean {
|
||||||
return at_bottom() || $next_row.get_offset_to_window().top <= bottom_threshold;
|
return at_bottom() || $next_row.get_offset_to_window().top <= bottom_threshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
function adjust(in_view, get_next_row) {
|
function adjust(
|
||||||
|
in_view: () => boolean,
|
||||||
|
get_next_row: ($message_row: JQuery) => JQuery,
|
||||||
|
): boolean {
|
||||||
// return true only if we make an actual adjustment, so
|
// return true only if we make an actual adjustment, so
|
||||||
// that we know to short circuit the other direction
|
// that we know to short circuit the other direction
|
||||||
if (in_view()) {
|
if (in_view()) {
|
||||||
|
@ -479,10 +538,11 @@ export function keep_pointer_in_view() {
|
||||||
adjust(message_is_far_enough_up, rows.prev_visible);
|
adjust(message_is_far_enough_up, rows.prev_visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
message_lists.current.select_id(rows.id($next_row), {from_scroll: true});
|
message_lists.current.select_id(rows.id($next_row)!, {from_scroll: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function scroll_to_selected() {
|
export function scroll_to_selected(): void {
|
||||||
|
assert(message_lists.current !== undefined);
|
||||||
const $selected_row = message_lists.current.selected_row();
|
const $selected_row = message_lists.current.selected_row();
|
||||||
if ($selected_row && $selected_row.length !== 0) {
|
if ($selected_row && $selected_row.length !== 0) {
|
||||||
recenter_view($selected_row);
|
recenter_view($selected_row);
|
||||||
|
@ -491,11 +551,11 @@ export function scroll_to_selected() {
|
||||||
|
|
||||||
export let scroll_to_selected_planned = false;
|
export let scroll_to_selected_planned = false;
|
||||||
|
|
||||||
export function plan_scroll_to_selected() {
|
export function plan_scroll_to_selected(): void {
|
||||||
scroll_to_selected_planned = true;
|
scroll_to_selected_planned = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function maybe_scroll_to_selected() {
|
export function maybe_scroll_to_selected(): void {
|
||||||
// If we have made a plan to scroll to the selected message but
|
// If we have made a plan to scroll to the selected message but
|
||||||
// deferred doing so, do so here.
|
// deferred doing so, do so here.
|
||||||
if (scroll_to_selected_planned) {
|
if (scroll_to_selected_planned) {
|
||||||
|
@ -504,9 +564,8 @@ export function maybe_scroll_to_selected() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initialize() {
|
export function initialize(): void {
|
||||||
$jwindow = $(window);
|
$jwindow = $(window);
|
||||||
|
|
||||||
// This handler must be placed before all resize handlers in our application
|
// This handler must be placed before all resize handlers in our application
|
||||||
$jwindow.on("resize", () => {
|
$jwindow.on("resize", () => {
|
||||||
dimensions.height.reset();
|
dimensions.height.reset();
|
Loading…
Reference in New Issue