2021-03-11 05:43:45 +01:00
|
|
|
import $ from "jquery";
|
2021-02-28 00:59:17 +01:00
|
|
|
import _ from "lodash";
|
2020-08-01 03:43:15 +02:00
|
|
|
|
2021-02-28 00:59:17 +01:00
|
|
|
import * as floating_recipient_bar from "./floating_recipient_bar";
|
2021-02-28 01:07:13 +01:00
|
|
|
import * as hash_util from "./hash_util";
|
2021-02-28 00:59:17 +01:00
|
|
|
import * as loading from "./loading";
|
2021-02-28 01:11:16 +01:00
|
|
|
import * as message_fetch from "./message_fetch";
|
2021-03-30 02:21:21 +02:00
|
|
|
import * as message_lists from "./message_lists";
|
2021-02-28 00:59:17 +01:00
|
|
|
import * as message_viewport from "./message_viewport";
|
2021-03-26 15:21:47 +01:00
|
|
|
import * as narrow_banner from "./narrow_banner";
|
2021-02-28 00:59:17 +01:00
|
|
|
import * as narrow_state from "./narrow_state";
|
2021-06-10 14:18:46 +02:00
|
|
|
import * as recent_topics_util from "./recent_topics_util";
|
2021-08-02 20:09:56 +02:00
|
|
|
import * as unread from "./unread";
|
2021-02-28 21:30:08 +01:00
|
|
|
import * as unread_ops from "./unread_ops";
|
2021-08-02 20:09:56 +02:00
|
|
|
import * as unread_ui from "./unread_ui";
|
2021-02-28 00:36:14 +01:00
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
let actively_scrolling = false;
|
2018-03-08 20:18:36 +01:00
|
|
|
|
2020-06-18 08:29:08 +02:00
|
|
|
// Tracks whether the next scroll that will complete is initiated by
|
|
|
|
// code, not the user, and thus should avoid moving the selected
|
|
|
|
// message.
|
|
|
|
let update_selection_on_next_scroll = true;
|
2021-02-28 00:59:17 +01:00
|
|
|
|
|
|
|
export function suppress_selection_update_on_next_scroll() {
|
2020-06-18 08:29:08 +02:00
|
|
|
update_selection_on_next_scroll = false;
|
2021-02-28 00:59:17 +01:00
|
|
|
}
|
2020-06-18 08:29:08 +02:00
|
|
|
|
2020-05-24 15:27:58 +02:00
|
|
|
let loading_older_messages_indicator_showing = false;
|
2020-05-26 16:27:06 +02:00
|
|
|
let loading_newer_messages_indicator_showing = false;
|
2021-02-28 00:59:17 +01:00
|
|
|
|
|
|
|
export function show_loading_older() {
|
2020-05-24 15:27:58 +02:00
|
|
|
if (!loading_older_messages_indicator_showing) {
|
2020-07-15 00:34:28 +02:00
|
|
|
loading.make_indicator($("#loading_older_messages_indicator"), {abs_positioned: true});
|
2020-05-24 15:27:58 +02:00
|
|
|
loading_older_messages_indicator_showing = true;
|
2018-03-08 20:18:36 +01:00
|
|
|
floating_recipient_bar.hide();
|
|
|
|
}
|
2021-02-28 00:59:17 +01:00
|
|
|
}
|
2018-03-08 20:18:36 +01:00
|
|
|
|
2021-02-28 00:59:17 +01:00
|
|
|
export function hide_loading_older() {
|
2020-05-24 15:27:58 +02:00
|
|
|
if (loading_older_messages_indicator_showing) {
|
|
|
|
loading.destroy_indicator($("#loading_older_messages_indicator"));
|
|
|
|
loading_older_messages_indicator_showing = false;
|
2018-03-08 20:18:36 +01:00
|
|
|
}
|
2021-02-28 00:59:17 +01:00
|
|
|
}
|
2018-03-08 20:18:36 +01:00
|
|
|
|
2021-02-28 00:59:17 +01:00
|
|
|
export function show_loading_newer() {
|
2020-05-26 16:27:06 +02:00
|
|
|
if (!loading_newer_messages_indicator_showing) {
|
|
|
|
$(".bottom-messages-logo").show();
|
2020-07-15 00:34:28 +02:00
|
|
|
loading.make_indicator($("#loading_newer_messages_indicator"), {abs_positioned: true});
|
2020-05-26 16:27:06 +02:00
|
|
|
loading_newer_messages_indicator_showing = true;
|
|
|
|
floating_recipient_bar.hide();
|
|
|
|
}
|
2021-02-28 00:59:17 +01:00
|
|
|
}
|
2020-05-26 16:27:06 +02:00
|
|
|
|
2021-02-28 00:59:17 +01:00
|
|
|
export function hide_loading_newer() {
|
2020-05-26 16:27:06 +02:00
|
|
|
if (loading_newer_messages_indicator_showing) {
|
|
|
|
$(".bottom-messages-logo").hide();
|
|
|
|
loading.destroy_indicator($("#loading_newer_messages_indicator"));
|
|
|
|
loading_newer_messages_indicator_showing = false;
|
|
|
|
}
|
2021-02-28 00:59:17 +01:00
|
|
|
}
|
2020-05-26 16:27:06 +02:00
|
|
|
|
2021-02-28 00:59:17 +01:00
|
|
|
export function hide_indicators() {
|
|
|
|
hide_loading_older();
|
|
|
|
hide_loading_newer();
|
|
|
|
}
|
2018-03-09 22:12:38 +01:00
|
|
|
|
2021-02-28 00:59:17 +01:00
|
|
|
export function show_history_limit_notice() {
|
2020-06-14 12:33:12 +02:00
|
|
|
$(".top-messages-logo").hide();
|
|
|
|
$(".history-limited-box").show();
|
2021-03-26 15:21:47 +01:00
|
|
|
narrow_banner.hide_empty_narrow_message();
|
2021-02-28 00:59:17 +01:00
|
|
|
}
|
2020-06-14 12:33:12 +02:00
|
|
|
|
2021-02-28 00:59:17 +01:00
|
|
|
export function hide_history_limit_notice() {
|
2020-06-14 12:33:12 +02:00
|
|
|
$(".top-messages-logo").show();
|
|
|
|
$(".history-limited-box").hide();
|
2021-02-28 00:59:17 +01:00
|
|
|
}
|
2020-06-14 12:33:12 +02:00
|
|
|
|
2021-02-28 00:59:17 +01:00
|
|
|
export function hide_end_of_results_notice() {
|
2020-06-14 12:33:12 +02:00
|
|
|
$(".all-messages-search-caution").hide();
|
2021-02-28 00:59:17 +01:00
|
|
|
}
|
2020-06-14 12:33:12 +02:00
|
|
|
|
2021-02-28 00:59:17 +01:00
|
|
|
export function show_end_of_results_notice() {
|
2020-06-14 12:33:12 +02:00
|
|
|
$(".all-messages-search-caution").show();
|
2022-01-19 21:46:03 +01:00
|
|
|
|
2020-06-14 12:33:12 +02:00
|
|
|
// Set the link to point to this search with streams:public added.
|
2022-01-19 11:10:21 +01:00
|
|
|
// Note that element we adjust is not visible to spectators.
|
2021-11-29 07:48:17 +01:00
|
|
|
const operators = narrow_state.filter().operators();
|
|
|
|
const update_hash = hash_util.search_public_streams_notice_url(operators);
|
2020-06-20 05:48:18 +02:00
|
|
|
$(".all-messages-search-caution a.search-shared-history").attr("href", update_hash);
|
2021-02-28 00:59:17 +01:00
|
|
|
}
|
2020-06-14 12:33:12 +02:00
|
|
|
|
2021-02-28 00:59:17 +01:00
|
|
|
export function update_top_of_narrow_notices(msg_list) {
|
2020-06-14 12:33:12 +02:00
|
|
|
// Assumes that the current state is all notices hidden (i.e. this
|
|
|
|
// will not hide a notice that should not be there)
|
2021-03-30 02:21:21 +02:00
|
|
|
if (msg_list !== message_lists.current) {
|
2020-06-14 12:33:12 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-30 02:21:21 +02:00
|
|
|
if (
|
|
|
|
msg_list.data.fetch_status.has_found_oldest() &&
|
|
|
|
message_lists.current !== message_lists.home
|
|
|
|
) {
|
2020-06-14 12:33:12 +02:00
|
|
|
const filter = narrow_state.filter();
|
2021-06-10 14:18:46 +02:00
|
|
|
if (filter === undefined && recent_topics_util.is_visible()) {
|
2020-07-05 12:19:09 +02:00
|
|
|
// user moved away from the narrow / filter to recent topics.
|
|
|
|
return;
|
|
|
|
}
|
2020-06-14 12:33:12 +02:00
|
|
|
// Potentially display the notice that lets users know
|
|
|
|
// that not all messages were searched. One could
|
|
|
|
// imagine including `filter.is_search()` in these
|
|
|
|
// conditions, but there's a very legitimate use case
|
|
|
|
// for moderation of searching for all messages sent
|
|
|
|
// by a potential spammer user.
|
2020-07-15 00:34:28 +02:00
|
|
|
if (
|
|
|
|
!filter.contains_only_private_messages() &&
|
2020-06-14 12:33:12 +02:00
|
|
|
!filter.includes_full_stream_history() &&
|
2020-07-15 00:34:28 +02:00
|
|
|
!filter.is_personal_filter()
|
|
|
|
) {
|
2021-02-28 00:59:17 +01:00
|
|
|
show_end_of_results_notice();
|
2020-06-14 12:33:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg_list.data.fetch_status.history_limited()) {
|
2021-02-28 00:59:17 +01:00
|
|
|
show_history_limit_notice();
|
2020-06-14 12:33:12 +02:00
|
|
|
}
|
2021-02-28 00:59:17 +01:00
|
|
|
}
|
2020-06-14 12:33:12 +02:00
|
|
|
|
2021-02-28 00:59:17 +01:00
|
|
|
export function hide_top_of_narrow_notices() {
|
|
|
|
hide_end_of_results_notice();
|
|
|
|
hide_history_limit_notice();
|
|
|
|
}
|
2020-06-14 12:33:12 +02:00
|
|
|
|
2022-02-14 17:43:32 +01:00
|
|
|
let hide_scroll_to_bottom_timer;
|
|
|
|
export function hide_scroll_to_bottom() {
|
|
|
|
const $show_scroll_to_bottom_button = $("#scroll-to-bottom-button-container");
|
|
|
|
if (message_viewport.bottom_message_visible() || message_lists.current.empty()) {
|
|
|
|
// If last message is visible, just hide the
|
|
|
|
// scroll to bottom button.
|
|
|
|
$show_scroll_to_bottom_button.hide();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait before hiding to allow user time to click on the button.
|
|
|
|
hide_scroll_to_bottom_timer = setTimeout(() => {
|
|
|
|
// Don't hide if user is hovered on it.
|
|
|
|
if (
|
|
|
|
!narrow_state.narrowed_by_topic_reply() &&
|
|
|
|
!$show_scroll_to_bottom_button.get(0).matches(":hover")
|
|
|
|
) {
|
|
|
|
$show_scroll_to_bottom_button.fadeOut(500);
|
|
|
|
}
|
|
|
|
}, 3000);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function show_scroll_to_bottom_button() {
|
|
|
|
if (message_viewport.bottom_message_visible()) {
|
|
|
|
// Only show scroll to bottom button when
|
|
|
|
// last message is not visible in the
|
|
|
|
// current scroll position.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
clearTimeout(hide_scroll_to_bottom_timer);
|
|
|
|
$("#scroll-to-bottom-button-container").fadeIn(500);
|
|
|
|
}
|
|
|
|
|
|
|
|
$(document).on("keydown", (e) => {
|
|
|
|
if (e.shiftKey || e.ctrlKey || e.metaKey) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Instantly hide scroll to bottom button on any keypress.
|
|
|
|
// Keyboard users are very less likely to use this button.
|
|
|
|
$("#scroll-to-bottom-button-container").hide();
|
|
|
|
});
|
|
|
|
|
2021-02-28 00:59:17 +01:00
|
|
|
export function is_actively_scrolling() {
|
2018-03-08 20:18:36 +01:00
|
|
|
return actively_scrolling;
|
2021-02-28 00:59:17 +01:00
|
|
|
}
|
2018-03-08 20:18:36 +01:00
|
|
|
|
2021-02-28 00:59:17 +01:00
|
|
|
export function scroll_finished() {
|
2018-03-08 20:18:36 +01:00
|
|
|
actively_scrolling = false;
|
2022-02-14 17:43:32 +01:00
|
|
|
hide_scroll_to_bottom();
|
2018-03-08 20:18:36 +01:00
|
|
|
|
2020-07-04 16:25:41 +02:00
|
|
|
if (!$("#message_feed_container").hasClass("active")) {
|
2018-03-08 20:41:43 +01:00
|
|
|
return;
|
2018-03-08 20:18:36 +01:00
|
|
|
}
|
2018-03-08 20:41:43 +01:00
|
|
|
|
2020-06-18 08:29:08 +02:00
|
|
|
if (update_selection_on_next_scroll) {
|
2018-03-08 20:41:43 +01:00
|
|
|
message_viewport.keep_pointer_in_view();
|
|
|
|
} else {
|
2020-06-18 08:29:08 +02:00
|
|
|
update_selection_on_next_scroll = true;
|
2018-03-08 20:41:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
floating_recipient_bar.update();
|
|
|
|
|
2018-03-08 20:47:52 +01:00
|
|
|
if (message_viewport.at_top()) {
|
2018-03-09 02:23:49 +01:00
|
|
|
message_fetch.maybe_load_older_messages({
|
2021-03-30 02:21:21 +02:00
|
|
|
msg_list: message_lists.current,
|
2018-03-08 20:41:43 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-03-11 20:19:30 +01:00
|
|
|
if (message_viewport.at_bottom()) {
|
|
|
|
message_fetch.maybe_load_newer_messages({
|
2021-03-30 02:21:21 +02:00
|
|
|
msg_list: message_lists.current,
|
2018-03-11 20:19:30 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-03-08 20:41:43 +01:00
|
|
|
// When the window scrolls, it may cause some messages to
|
|
|
|
// enter the screen and become read. Calling
|
|
|
|
// unread_ops.process_visible will update necessary
|
|
|
|
// data structures and DOM elements.
|
|
|
|
setTimeout(unread_ops.process_visible, 0);
|
2021-02-28 00:59:17 +01:00
|
|
|
}
|
2018-03-08 20:18:36 +01:00
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
let scroll_timer;
|
2018-03-08 20:18:36 +01:00
|
|
|
function scroll_finish() {
|
|
|
|
actively_scrolling = true;
|
2022-02-14 17:43:32 +01:00
|
|
|
show_scroll_to_bottom_button();
|
2018-03-08 20:18:36 +01:00
|
|
|
clearTimeout(scroll_timer);
|
2021-02-28 00:59:17 +01:00
|
|
|
scroll_timer = setTimeout(scroll_finished, 100);
|
2018-03-08 20:18:36 +01:00
|
|
|
}
|
|
|
|
|
2021-02-28 00:59:17 +01:00
|
|
|
export function initialize() {
|
2022-01-25 11:36:19 +01:00
|
|
|
message_viewport.$message_pane.on(
|
2020-07-20 21:26:58 +02:00
|
|
|
"scroll",
|
2020-07-15 00:34:28 +02:00
|
|
|
_.throttle(() => {
|
|
|
|
unread_ops.process_visible();
|
|
|
|
scroll_finish();
|
|
|
|
}, 50),
|
|
|
|
);
|
2020-06-18 08:37:25 +02:00
|
|
|
|
|
|
|
// Scroll handler that marks messages as read when you scroll past them.
|
2020-07-15 01:29:15 +02:00
|
|
|
$(document).on("message_selected.zulip", (event) => {
|
2020-06-18 08:37:25 +02:00
|
|
|
if (event.id === -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-13 18:29:24 +02:00
|
|
|
if (event.mark_read && event.previously_selected_id !== -1) {
|
2020-06-18 08:37:25 +02:00
|
|
|
// Mark messages between old pointer and new pointer as read
|
|
|
|
let messages;
|
2020-09-13 18:29:24 +02:00
|
|
|
if (event.id < event.previously_selected_id) {
|
|
|
|
messages = event.msg_list.message_range(event.id, event.previously_selected_id);
|
2020-06-18 08:37:25 +02:00
|
|
|
} else {
|
2020-09-13 18:29:24 +02:00
|
|
|
messages = event.msg_list.message_range(event.previously_selected_id, event.id);
|
2020-06-18 08:37:25 +02:00
|
|
|
}
|
|
|
|
if (event.msg_list.can_mark_messages_read()) {
|
2020-07-15 01:29:15 +02:00
|
|
|
unread_ops.notify_server_messages_read(messages, {from: "pointer"});
|
2021-08-02 20:09:56 +02:00
|
|
|
} else if (
|
|
|
|
unread.get_unread_messages(messages).length !== 0 &&
|
|
|
|
// The below checks might seem redundant, but it's
|
|
|
|
// possible this logic, which runs after a delay, lost
|
|
|
|
// a race with switching to another view, like Recent
|
|
|
|
// Topics, and we don't want to displ[ay this banner
|
|
|
|
// in such a view.
|
|
|
|
//
|
|
|
|
// This can likely be fixed more cleanly with another approach.
|
|
|
|
narrow_state.filter() !== undefined &&
|
|
|
|
message_lists.current === event.msg_list
|
|
|
|
) {
|
|
|
|
unread_ui.notify_messages_remain_unread();
|
2020-06-18 08:37:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2021-02-28 00:59:17 +01:00
|
|
|
}
|