recent_topics: Split into three modules.

We split recent_topics module into recent_topics_(ui + data + util).

This allows us to reduce cyclical dependencies which were
created due to large list of imports in recent topics. Also, this
refactor on its own makes sense.
This commit is contained in:
Aman Agrawal 2021-06-10 12:18:46 +00:00 committed by Tim Abbott
parent eb1d8b1a96
commit 88454307cd
29 changed files with 194 additions and 178 deletions

View File

@ -30,9 +30,8 @@ mock_esm("../../static/js/notifications", {
mock_esm("../../static/js/reload_state", {
is_in_progress: () => false,
});
mock_esm("../../static/js/recent_topics", {
mock_esm("../../static/js/recent_topics_util", {
is_visible: noop,
set_compose_defaults: noop,
});
mock_esm("../../static/js/drafts", {
update_draft: noop,

View File

@ -7,6 +7,10 @@ const {mock_cjs, mock_esm, set_global, zrequire} = require("../zjsunit/namespace
const {run_test} = require("../zjsunit/test");
const $ = require("../zjsunit/zjquery");
mock_esm("../../static/js/recent_topics_util", {
is_visible: () => false,
});
// Mocking and stubbing things
mock_cjs("jquery", $);
set_global("document", "document-stub");

View File

@ -60,7 +60,7 @@ message_lists.current = {};
message_lists.home = {};
const message_store = zrequire("message_store");
const recent_topics = zrequire("recent_topics");
const recent_topics_util = zrequire("recent_topics_util");
const stream_data = zrequire("stream_data");
const unread = zrequire("unread");
const unread_ops = zrequire("unread_ops");
@ -90,7 +90,7 @@ run_test("unread_ops", (override) => {
];
// We don't want recent topics to process message for this test.
override(recent_topics, "is_visible", () => false);
override(recent_topics_util, "is_visible", () => false);
// Show message_viewport as not visible so that messages will be stored as unread.
override(message_viewport, "is_visible_and_focused", () => false);

View File

@ -43,7 +43,8 @@ const hash_util = zrequire("hash_util");
const hashchange = zrequire("hashchange");
const stream_data = zrequire("stream_data");
const recent_topics = zrequire("recent_topics");
const recent_topics_util = zrequire("recent_topics_util");
const recent_topics_ui = zrequire("recent_topics_ui");
run_test("operators_round_trip", () => {
let operators;
@ -170,8 +171,8 @@ run_test("hash_interactions", (override) => {
window_stub = $.create("window-stub");
page_params.default_view = "recent_topics";
override(recent_topics, "show", () => {});
override(recent_topics, "is_visible", () => false);
override(recent_topics_ui, "show", () => {});
override(recent_topics_util, "is_visible", () => false);
const helper = test_helper({override, change_tab: true});
window.location.hash = "#all_messages";
@ -285,6 +286,8 @@ run_test("hash_interactions", (override) => {
});
run_test("save_narrow", (override) => {
override(recent_topics_util, "is_visible", () => false);
const helper = test_helper({override});
let operators = [{operator: "is", operand: "private"}];

View File

@ -81,7 +81,7 @@ mock_esm("../../static/js/hotspots", {
is_open: () => false,
});
mock_esm("../../static/js/recent_topics", {
mock_esm("../../static/js/recent_topics_util", {
is_visible: () => false,
is_in_focus: () => false,
});

View File

@ -21,7 +21,7 @@ mock_esm("../../static/js/message_list_view", {
MessageListView,
});
mock_esm("../../static/js/recent_topics", {
mock_esm("../../static/js/recent_topics_ui", {
process_messages: noop,
});
mock_esm("../../static/js/ui_report", {

View File

@ -38,8 +38,7 @@ const top_left_corner = mock_esm("../../static/js/top_left_corner");
const typing_events = mock_esm("../../static/js/typing_events");
const ui_util = mock_esm("../../static/js/ui_util");
const unread_ops = mock_esm("../../static/js/unread_ops");
mock_esm("../../static/js/recent_topics", {
hide: () => {},
mock_esm("../../static/js/recent_topics_util", {
is_visible: () => {},
});

View File

@ -103,9 +103,6 @@ mock_esm("../../static/js/muting", {
mock_esm("../../static/js/narrow", {
set_narrow_title: noop,
});
mock_esm("../../static/js/popovers", {
any_active: () => false,
});
mock_esm("../../static/js/recent_senders", {
get_topic_recent_senders: () => [1, 2],
});
@ -172,7 +169,8 @@ set_global("localStorage", {
const {all_messages_data} = zrequire("all_messages_data");
const people = zrequire("people");
const rt = zrequire("recent_topics");
const rt = zrequire("recent_topics_ui");
const rt_data = zrequire("recent_topics_data");
people.is_my_user_id = (id) => id === 1;
people.sender_info_for_recent_topics_row = (ids) => ids;
@ -654,7 +652,7 @@ test("basic assertions", (override) => {
rt.set_default_focus();
rt.set_filter("all");
rt.process_messages(messages);
let all_topics = rt.get();
let all_topics = rt_data.get();
// update a message
generate_topic_data([[1, "topic-7", 1, false, true]]);
@ -703,7 +701,7 @@ test("basic assertions", (override) => {
"4:topic-10,1:topic-7,1:topic-6,1:topic-5,1:topic-4,1:topic-3,1:topic-2,1:topic-1",
);
rt.process_message({
rt_data.process_message({
type: "private",
});
@ -724,7 +722,7 @@ test("basic assertions", (override) => {
verify_topic_data(all_topics, stream1, topic4, messages[4].id, false);
// topic3 now participated
rt.process_message({
rt_data.process_message({
stream_id: stream1,
id: (id += 1),
topic: topic3,
@ -732,7 +730,7 @@ test("basic assertions", (override) => {
type: "stream",
});
all_topics = rt.get();
all_topics = rt_data.get();
assert.equal(
Array.from(all_topics.keys()).toString(),
"1:topic-3,4:topic-10,1:topic-7,1:topic-6,1:topic-5,1:topic-4,1:topic-2,1:topic-1",
@ -741,7 +739,7 @@ test("basic assertions", (override) => {
// Send new message to topic7 (muted)
// The topic will be hidden when displayed
rt.process_message({
rt_data.process_message({
stream_id: stream1,
id: (id += 1),
topic: topic7,
@ -749,7 +747,7 @@ test("basic assertions", (override) => {
type: "stream",
});
all_topics = rt.get();
all_topics = rt_data.get();
assert.equal(
Array.from(all_topics.keys()).toString(),
"1:topic-7,1:topic-3,4:topic-10,1:topic-6,1:topic-5,1:topic-4,1:topic-2,1:topic-1",
@ -772,7 +770,7 @@ test("test_reify_local_echo_message", (override) => {
rt.set_filter("all");
rt.process_messages(messages);
rt.process_message({
rt_data.process_message({
stream_id: stream1,
id: 1000.01,
topic: topic7,
@ -781,14 +779,14 @@ test("test_reify_local_echo_message", (override) => {
});
assert.equal(
rt.reify_message_id_if_available({
rt_data.reify_message_id_if_available({
old_id: 1000.01,
new_id: 1001,
}),
true,
);
rt.process_message({
rt_data.process_message({
stream_id: stream1,
id: 1001.01,
topic: topic7,
@ -797,7 +795,7 @@ test("test_reify_local_echo_message", (override) => {
});
// A new message arrived in the same topic before we could reify the message_id
rt.process_message({
rt_data.process_message({
stream_id: stream1,
id: 1003,
topic: topic7,
@ -806,7 +804,7 @@ test("test_reify_local_echo_message", (override) => {
});
assert.equal(
rt.reify_message_id_if_available({
rt_data.reify_message_id_if_available({
old_id: 1000.01,
new_id: 1001,
}),
@ -824,14 +822,14 @@ test("test_delete_messages", (override) => {
let reduced_msgs = messages.slice(1);
override(all_messages_data, "all_messages", () => reduced_msgs);
let all_topics = rt.get();
let all_topics = rt_data.get();
assert.equal(
Array.from(all_topics.keys()).toString(),
"4:topic-10,1:topic-7,1:topic-6,1:topic-5,1:topic-4,1:topic-3,1:topic-2,1:topic-1",
);
rt.update_topics_of_deleted_message_ids([messages[0].id]);
all_topics = rt.get();
all_topics = rt_data.get();
assert.equal(
Array.from(all_topics.keys()).toString(),
"4:topic-10,1:topic-7,1:topic-6,1:topic-5,1:topic-4,1:topic-3,1:topic-2",
@ -842,7 +840,7 @@ test("test_delete_messages", (override) => {
rt.update_topics_of_deleted_message_ids([messages[1].id, messages[2].id]);
all_topics = rt.get();
all_topics = rt_data.get();
assert.equal(
Array.from(all_topics.keys()).toString(),
"4:topic-10,1:topic-7,1:topic-6,1:topic-5,1:topic-4,1:topic-3",
@ -861,7 +859,7 @@ test("test_topic_edit", (override) => {
rt.set_filter("all");
rt.process_messages(messages);
let all_topics = rt.get();
let all_topics = rt_data.get();
assert.equal(
Array.from(all_topics.keys()).toString(),
"4:topic-10,1:topic-7,1:topic-6,1:topic-5,1:topic-4,1:topic-3,1:topic-2,1:topic-1",
@ -875,7 +873,7 @@ test("test_topic_edit", (override) => {
messages[7].topic = topic8;
messages[8].topic = topic8;
rt.process_topic_edit(stream1, topic6, topic8);
all_topics = rt.get();
all_topics = rt_data.get();
verify_topic_data(all_topics, stream1, topic8, messages[8].id, true);
assert.equal(all_topics.get(get_topic_key(stream1, topic6)), undefined);
@ -886,7 +884,7 @@ test("test_topic_edit", (override) => {
messages[0].stream_id = stream2;
rt.process_topic_edit(stream1, topic1, topic1, stream2);
all_topics = rt.get();
all_topics = rt_data.get();
assert.equal(all_topics.get(get_topic_key(stream1, topic1)), undefined);
verify_topic_data(all_topics, stream2, topic1, messages[0].id, true);
@ -898,7 +896,7 @@ test("test_topic_edit", (override) => {
messages[0].stream_id = stream3;
messages[0].topic = topic9;
rt.process_topic_edit(stream2, topic1, topic9, stream3);
all_topics = rt.get();
all_topics = rt_data.get();
assert.equal(all_topics.get(get_topic_key(stream2, topic1)), undefined);
verify_topic_data(all_topics, stream3, topic9, messages[0].id, true);
@ -907,7 +905,7 @@ test("test_topic_edit", (override) => {
messages[0].stream_id = stream5;
messages[0].topic = topic8;
rt.process_topic_edit(stream3, topic9, topic8, stream5);
all_topics = rt.get();
all_topics = rt_data.get();
assert.equal(rt.filters_should_hide_topic(all_topics.get("5:topic-8")), true);
});

View File

@ -30,7 +30,7 @@ mock_esm("../../static/js/all_messages_data", {
const message_lists = mock_esm("../../static/js/message_lists", {
current: {},
});
mock_esm("../../static/js/recent_topics", {
mock_esm("../../static/js/recent_topics_ui", {
complete_rerender: () => {},
});
mock_esm("../../static/js/settings_notifications", {

View File

@ -32,7 +32,7 @@ import * as overlays from "./overlays";
import {page_params} from "./page_params";
import * as popovers from "./popovers";
import * as reactions from "./reactions";
import * as recent_topics from "./recent_topics";
import * as recent_topics_ui from "./recent_topics_ui";
import * as rows from "./rows";
import * as server_events from "./server_events";
import * as settings_panel_menu from "./settings_panel_menu";
@ -407,7 +407,7 @@ export function initialize() {
$("body").on("click", "#recent_topics_table .on_hover_topic_unmute", (e) => {
e.stopPropagation();
const $elt = $(e.target);
recent_topics.focus_clicked_element($elt, recent_topics.COLUMNS.mute);
recent_topics_ui.focus_clicked_element($elt, recent_topics_ui.COLUMNS.mute);
mute_or_unmute_topic($elt, false);
});
@ -416,18 +416,18 @@ export function initialize() {
$("body").on("click", "#recent_topics_table .on_hover_topic_mute", (e) => {
e.stopPropagation();
const $elt = $(e.target);
recent_topics.focus_clicked_element($elt, recent_topics.COLUMNS.mute);
recent_topics_ui.focus_clicked_element($elt, recent_topics_ui.COLUMNS.mute);
mute_or_unmute_topic($elt, true);
});
$("body").on("click", "#recent_topics_search", (e) => {
e.stopPropagation();
recent_topics.change_focused_element($(e.target), "click");
recent_topics_ui.change_focused_element($(e.target), "click");
});
$("body").on("click", "#recent_topics_table .on_hover_topic_read", (e) => {
e.stopPropagation();
recent_topics.focus_clicked_element($(e.target), recent_topics.COLUMNS.read);
recent_topics_ui.focus_clicked_element($(e.target), recent_topics_ui.COLUMNS.read);
const stream_id = Number.parseInt($(e.currentTarget).attr("data-stream-id"), 10);
const topic = $(e.currentTarget).attr("data-topic-name");
unread_ops.mark_topic_as_read(stream_id, topic);
@ -437,20 +437,20 @@ export function initialize() {
$("body").on("click", ".btn-recent-filters", (e) => {
e.stopPropagation();
recent_topics.change_focused_element($(e.target), "click");
recent_topics.set_filter(e.currentTarget.dataset.filter);
recent_topics.update_filters_view();
recent_topics_ui.change_focused_element($(e.target), "click");
recent_topics_ui.set_filter(e.currentTarget.dataset.filter);
recent_topics_ui.update_filters_view();
});
$("body").on("click", "td.recent_topic_stream", (e) => {
e.stopPropagation();
recent_topics.focus_clicked_element($(e.target), recent_topics.COLUMNS.stream);
recent_topics_ui.focus_clicked_element($(e.target), recent_topics_ui.COLUMNS.stream);
window.location.href = $(e.currentTarget).find("a").attr("href");
});
$("body").on("click", "td.recent_topic_name", (e) => {
e.stopPropagation();
recent_topics.focus_clicked_element($(e.target), recent_topics.COLUMNS.topic);
recent_topics_ui.focus_clicked_element($(e.target), recent_topics_ui.COLUMNS.topic);
window.location.href = $(e.currentTarget).find("a").attr("href");
});
@ -459,7 +459,7 @@ export function initialize() {
"keyup",
"#recent_topics_search",
_.debounce(() => {
recent_topics.update_filters_view();
recent_topics_ui.update_filters_view();
// Wait for user to go idle before initiating search.
}, 300),
);
@ -467,7 +467,7 @@ export function initialize() {
$("body").on("click", "#recent_topics_search_clear", (e) => {
e.stopPropagation();
$("#recent_topics_search").val("");
recent_topics.update_filters_view();
recent_topics_ui.update_filters_view();
});
// RECIPIENT BARS

View File

@ -20,7 +20,8 @@ import * as narrow_state from "./narrow_state";
import * as notifications from "./notifications";
import {page_params} from "./page_params";
import * as people from "./people";
import * as recent_topics from "./recent_topics";
import * as recent_topics_ui from "./recent_topics_ui";
import * as recent_topics_util from "./recent_topics_util";
import * as reload_state from "./reload_state";
import * as stream_bar from "./stream_bar";
import * as stream_data from "./stream_data";
@ -299,8 +300,8 @@ export function respond_to_message(opts) {
let message;
let msg_type;
if (recent_topics.is_visible()) {
message = recent_topics.get_focused_row_message();
if (recent_topics_util.is_visible()) {
message = recent_topics_ui.get_focused_row_message();
if (message === undefined) {
// Open empty compose with nothing pre-filled since
// user is not focused on any table row.

View File

@ -7,7 +7,7 @@ import * as message_store from "./message_store";
import * as narrow_state from "./narrow_state";
import * as people from "./people";
import * as popovers from "./popovers";
import * as recent_topics from "./recent_topics";
import * as recent_topics_util from "./recent_topics_util";
function update_stream_button(btn_text, title) {
$("#left_bar_compose_stream_button_big").text(btn_text);
@ -101,7 +101,7 @@ export function update_reply_recipient_label(message) {
export function initialize() {
// When the message selection changes, change the label on the Reply button.
$(document).on("message_selected.zulip", () => {
if (recent_topics.is_visible()) {
if (recent_topics_util.is_visible()) {
// message_selected events can occur with recent topics
// open due to "All messages" loading in the background,
// so we return without calling changing button state.

View File

@ -16,7 +16,7 @@ import {page_params} from "./page_params";
import * as people from "./people";
import * as pm_list from "./pm_list";
import * as popovers from "./popovers";
import * as recent_topics from "./recent_topics";
import * as recent_topics_data from "./recent_topics_data";
import * as rows from "./rows";
import * as sent_messages from "./sent_messages";
import * as stream_list from "./stream_list";
@ -336,7 +336,7 @@ export function reify_message_id(local_id, server_id) {
message_store.reify_message_id(opts);
update_message_lists(opts);
notifications.reify_message_id(opts);
recent_topics.reify_message_id_if_available(opts);
recent_topics_data.reify_message_id_if_available(opts);
}
export function update_message_lists({old_id, new_id}) {

View File

@ -15,7 +15,8 @@ import * as narrow from "./narrow";
import * as navigate from "./navigate";
import * as overlays from "./overlays";
import {page_params} from "./page_params";
import * as recent_topics from "./recent_topics";
import * as recent_topics_ui from "./recent_topics_ui";
import * as recent_topics_util from "./recent_topics_util";
import * as search from "./search";
import * as settings from "./settings";
import * as settings_panel_menu from "./settings_panel_menu";
@ -58,8 +59,8 @@ function set_hash(hash) {
}
function maybe_hide_recent_topics() {
if (recent_topics.is_visible()) {
recent_topics.hide();
if (recent_topics_util.is_visible()) {
recent_topics_ui.hide();
return true;
}
return false;
@ -105,7 +106,7 @@ function show_default_view() {
// We only allow all_messages and recent_topics
// to be rendered without a hash.
if (page_params.default_view === "recent_topics") {
recent_topics.show();
recent_topics_ui.show();
} else if (page_params.default_view === "all_messages") {
show_all_message_view();
} else {
@ -162,7 +163,7 @@ function do_hashchange_normal(from_reload) {
show_default_view();
break;
case "#recent_topics":
recent_topics.show();
recent_topics_ui.show();
break;
case "#all_messages":
show_all_message_view();

View File

@ -30,7 +30,8 @@ import * as overlays from "./overlays";
import {page_params} from "./page_params";
import * as popovers from "./popovers";
import * as reactions from "./reactions";
import * as recent_topics from "./recent_topics";
import * as recent_topics_ui from "./recent_topics_ui";
import * as recent_topics_util from "./recent_topics_util";
import * as search from "./search";
import * as settings_data from "./settings_data";
import * as stream_list from "./stream_list";
@ -222,10 +223,10 @@ export function in_content_editable_widget(e) {
// Returns true if we handled it, false if the browser should.
export function process_escape_key(e) {
if (
recent_topics.is_in_focus() &&
recent_topics_util.is_in_focus() &&
// This will return false if `e.target` is not
// any of the recent topics elements by design.
recent_topics.change_focused_element($(e.target), "escape")
recent_topics_ui.change_focused_element($(e.target), "escape")
) {
// Recent topics uses escape to switch focus from RT search / filters to topics table.
// If focus is already on the table it returns false.
@ -549,8 +550,8 @@ export function process_hotkey(e, hotkey) {
case "tab":
case "shift_tab":
case "open_recent_topics":
if (recent_topics.is_in_focus()) {
return recent_topics.change_focused_element($(e.target), event_name);
if (recent_topics_util.is_in_focus()) {
return recent_topics_ui.change_focused_element($(e.target), event_name);
}
}
@ -816,7 +817,7 @@ export function process_hotkey(e, hotkey) {
// We don't want hotkeys below this to work when recent topics is
// open. These involve hotkeys that can only be performed on a message.
if (recent_topics.is_visible()) {
if (recent_topics_util.is_visible()) {
return false;
}

View File

@ -20,7 +20,7 @@ import * as notifications from "./notifications";
import {page_params} from "./page_params";
import * as pm_list from "./pm_list";
import * as recent_senders from "./recent_senders";
import * as recent_topics from "./recent_topics";
import * as recent_topics_ui from "./recent_topics_ui";
import * as resize from "./resize";
import * as stream_list from "./stream_list";
import * as stream_topic_history from "./stream_topic_history";
@ -132,7 +132,7 @@ export function insert_new_messages(messages, sent_by_this_client) {
notifications.received_messages(messages);
stream_list.update_streams_sidebar();
pm_list.update_private_messages();
recent_topics.process_messages(messages);
recent_topics_ui.process_messages(messages);
}
export function update_messages(events) {
@ -399,7 +399,7 @@ export function update_messages(events) {
new_stream_id: post_edit_stream_id,
new_topic: post_edit_topic,
});
recent_topics.process_topic_edit(...args);
recent_topics_ui.process_topic_edit(...args);
}
// Rerender "Message edit history" if it was open to the edited message.
@ -456,5 +456,5 @@ export function remove_messages(message_ids) {
list.remove_and_rerender(message_ids);
}
recent_senders.update_topics_of_deleted_message_ids(message_ids);
recent_topics.update_topics_of_deleted_message_ids(message_ids);
recent_topics_ui.update_topics_of_deleted_message_ids(message_ids);
}

View File

@ -14,7 +14,7 @@ import * as narrow_banner from "./narrow_banner";
import {page_params} from "./page_params";
import * as people from "./people";
import * as pm_list from "./pm_list";
import * as recent_topics from "./recent_topics";
import * as recent_topics_ui from "./recent_topics_ui";
import * as stream_data from "./stream_data";
import * as stream_list from "./stream_list";
import * as ui_report from "./ui_report";
@ -76,7 +76,7 @@ function process_result(data, opts) {
huddle_data.process_loaded_messages(messages);
stream_list.update_streams_sidebar();
pm_list.update_private_messages();
recent_topics.process_messages(messages);
recent_topics_ui.process_messages(messages);
stream_list.maybe_scroll_narrow_into_view();

View File

@ -25,7 +25,7 @@ import {page_params} from "./page_params";
import * as people from "./people";
import * as popovers from "./popovers";
import * as reactions from "./reactions";
import * as recent_topics from "./recent_topics";
import * as recent_topics_util from "./recent_topics_util";
import * as rendered_markdown from "./rendered_markdown";
import * as rows from "./rows";
import * as stream_data from "./stream_data";
@ -658,7 +658,7 @@ export class MessageListView {
const restore_scroll_position = () => {
if (
!recent_topics.is_visible() &&
!recent_topics_util.is_visible() &&
list === message_lists.current &&
orig_scrolltop_offset !== undefined
) {

View File

@ -9,7 +9,7 @@ import * as message_lists from "./message_lists";
import * as message_viewport from "./message_viewport";
import * as narrow_banner from "./narrow_banner";
import * as narrow_state from "./narrow_state";
import * as recent_topics from "./recent_topics";
import * as recent_topics_util from "./recent_topics_util";
import * as unread_ops from "./unread_ops";
let actively_scrolling = false;
@ -100,7 +100,7 @@ export function update_top_of_narrow_notices(msg_list) {
message_lists.current !== message_lists.home
) {
const filter = narrow_state.filter();
if (filter === undefined && recent_topics.is_visible()) {
if (filter === undefined && recent_topics_util.is_visible()) {
// user moved away from the narrow / filter to recent topics.
return;
}

View File

@ -6,7 +6,7 @@ import {$t} from "./i18n";
import * as narrow_state from "./narrow_state";
import {page_params} from "./page_params";
import * as peer_data from "./peer_data";
import * as recent_topics from "./recent_topics";
import * as recent_topics_util from "./recent_topics_util";
import * as rendered_markdown from "./rendered_markdown";
import * as search from "./search";
@ -20,7 +20,7 @@ function get_formatted_sub_count(sub_count) {
function make_message_view_header(filter) {
const message_view_header = {};
if (recent_topics.is_visible()) {
if (recent_topics_util.is_visible()) {
return {
title: $t({defaultMessage: "Recent topics"}),
icon: "clock-o",

View File

@ -15,7 +15,7 @@ import * as overlays from "./overlays";
import * as people from "./people";
import * as pm_list from "./pm_list";
import * as popovers from "./popovers";
import * as recent_topics from "./recent_topics";
import * as recent_topics_ui from "./recent_topics_ui";
import * as settings_muted_topics from "./settings_muted_topics";
import * as settings_muted_users from "./settings_muted_users";
import * as stream_data from "./stream_data";
@ -40,7 +40,7 @@ export function rerender_for_muted_topic(old_muted_topics) {
const maybe_affected_topics = _.unionWith(old_muted_topics, current_muted_topics, _.isEqual);
for (const topic_data of maybe_affected_topics) {
recent_topics.update_topic_is_muted(topic_data.stream_id, topic_data.topic);
recent_topics_ui.update_topic_is_muted(topic_data.stream_id, topic_data.topic);
}
}
@ -172,7 +172,7 @@ export function rerender_for_muted_user() {
// If a user is (un)muted, we want to update their avatars on the recent topics
// participants column.
recent_topics.complete_rerender();
recent_topics_ui.complete_rerender();
}
export function handle_user_updates(muted_user_ids) {

View File

@ -23,7 +23,8 @@ import * as narrow_state from "./narrow_state";
import * as notifications from "./notifications";
import {page_params} from "./page_params";
import * as people from "./people";
import * as recent_topics from "./recent_topics";
import * as recent_topics_ui from "./recent_topics_ui";
import * as recent_topics_util from "./recent_topics_util";
import * as resize from "./resize";
import * as search from "./search";
import * as search_pill from "./search_pill";
@ -187,8 +188,8 @@ export function activate(raw_operators, opts) {
or rerendering due to server-side changes.
*/
if (recent_topics.is_visible()) {
recent_topics.hide();
if (recent_topics_util.is_visible()) {
recent_topics_ui.hide();
}
const start_time = new Date();

View File

@ -0,0 +1,63 @@
import * as people from "./people";
import {get_topic_key} from "./recent_topics_util";
export const topics = new Map(); // Key is stream-id:topic.
export function process_message(msg) {
// This function returns if topic_data
// has changed or not.
if (msg.type !== "stream") {
// We don't process private messages yet.
return false;
}
// Initialize topic data
const key = get_topic_key(msg.stream_id, msg.topic);
if (!topics.has(key)) {
topics.set(key, {
last_msg_id: -1,
participated: false,
});
}
// Update topic data
const is_ours = people.is_my_user_id(msg.sender_id);
const topic_data = topics.get(key);
if (topic_data.last_msg_id < msg.id) {
// NOTE: This also stores locally echoed msg_id which
// has not been successfully received from the server.
// We store it now and reify it when response is available
// from server.
topic_data.last_msg_id = msg.id;
}
// TODO: Add backend support for participated topics.
// Currently participated === recently participated
// i.e. Only those topics are participated for which we have the user's
// message fetched in the topic. Ideally we would want this to be attached
// to topic info fetched from backend, which is currently not a thing.
topic_data.participated = is_ours || topic_data.participated;
return true;
}
function get_sorted_topics() {
// Sort all recent topics by last message time.
return new Map(
Array.from(topics.entries()).sort((a, b) => b[1].last_msg_id - a[1].last_msg_id),
);
}
export function get() {
return get_sorted_topics();
}
export function reify_message_id_if_available(opts) {
// We don't need to reify the message_id of the topic
// if a new message arrives in the topic from another user,
// since it replaces the last_msg_id of the topic which
// we were trying to reify.
for (const [, value] of topics.entries()) {
if (value.last_msg_id === opts.old_id) {
value.last_msg_id = opts.new_id;
return true;
}
}
return false;
}

View File

@ -5,7 +5,6 @@ import render_recent_topics_filters from "../templates/recent_topics_filters.hbs
import render_recent_topics_body from "../templates/recent_topics_table.hbs";
import * as compose_closed_ui from "./compose_closed_ui";
import * as compose_state from "./compose_state";
import * as hash_util from "./hash_util";
import {$t} from "./i18n";
import * as ListWidget from "./list_widget";
@ -18,10 +17,10 @@ import * as narrow from "./narrow";
import * as narrow_state from "./narrow_state";
import * as navbar_alerts from "./navbar_alerts";
import * as navigate from "./navigate";
import * as overlays from "./overlays";
import * as people from "./people";
import * as popovers from "./popovers";
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 * as stream_data from "./stream_data";
import * as stream_list from "./stream_list";
import * as sub_store from "./sub_store";
@ -29,7 +28,6 @@ import * as timerender from "./timerender";
import * as top_left_corner from "./top_left_corner";
import * as unread from "./unread";
const topics = new Map(); // Key is stream-id:topic.
let topics_widget;
// Sets the number of avatars to display.
// Rest of the avatars, if present, are displayed as {+x}
@ -47,7 +45,8 @@ const MAX_EXTRA_SENDERS = 10;
// So, we use table as a grid system and
// track the coordinates of the focus element via
// `row_focus` and `col_focus`.
let current_focus_elem = "table";
export let current_focus_elem = "table";
let row_focus = 0;
// Start focus on the topic column, so Down+Enter works to visit a topic.
let col_focus = 1;
@ -71,18 +70,6 @@ const ls = localstorage();
let filters = new Set();
export function is_in_focus() {
// Check if user is focused on
// recent topics.
return (
is_visible() &&
!compose_state.composing() &&
!popovers.any_active() &&
!overlays.is_active() &&
!$(".home-page-input").is(":focus")
);
}
export function clear_for_tests() {
filters.clear();
topics.clear();
@ -97,10 +84,6 @@ export function load_filters() {
filters = new Set(ls.get(ls_key));
}
function is_table_focused() {
return current_focus_elem === "table";
}
export function set_default_focus() {
// If at any point we are confused about the currently
// focused element, we switch focus to search.
@ -117,6 +100,10 @@ function get_min_load_count(already_rendered_count, load_count) {
return load_count;
}
function is_table_focused() {
return current_focus_elem === "table";
}
function set_table_focus(row, col) {
const topic_rows = $("#recent_topics_table table tbody tr");
if (topic_rows.length === 0 || row < 0 || row >= topic_rows.length) {
@ -208,10 +195,6 @@ function revive_current_focus() {
return true;
}
function get_topic_key(stream_id, topic) {
return stream_id + ":" + topic.toLowerCase();
}
export function process_messages(messages) {
// While this is inexpensive and handles all the cases itself,
// the UX can be bad if user wants to scroll down the list as
@ -232,65 +215,6 @@ export function process_messages(messages) {
}
}
export function process_message(msg) {
// This function returns if topic_data
// has changed or not.
if (msg.type !== "stream") {
// We don't process private messages yet.
return false;
}
// Initialize topic data
const key = get_topic_key(msg.stream_id, msg.topic);
if (!topics.has(key)) {
topics.set(key, {
last_msg_id: -1,
participated: false,
});
}
// Update topic data
const is_ours = people.is_my_user_id(msg.sender_id);
const topic_data = topics.get(key);
if (topic_data.last_msg_id < msg.id) {
// NOTE: This also stores locally echoed msg_id which
// has not been successfully received from the server.
// We store it now and reify it when response is available
// from server.
topic_data.last_msg_id = msg.id;
}
// TODO: Add backend support for participated topics.
// Currently participated === recently participated
// i.e. Only those topics are participated for which we have the user's
// message fetched in the topic. Ideally we would want this to be attached
// to topic info fetched from backend, which is currently not a thing.
topic_data.participated = is_ours || topic_data.participated;
return true;
}
export function reify_message_id_if_available(opts) {
// We don't need to reify the message_id of the topic
// if a new message arrives in the topic from another user,
// since it replaces the last_msg_id of the topic which
// we were trying to reify.
for (const [, value] of topics.entries()) {
if (value.last_msg_id === opts.old_id) {
value.last_msg_id = opts.new_id;
return true;
}
}
return false;
}
function get_sorted_topics() {
// Sort all recent topics by last message time.
return new Map(
Array.from(topics.entries()).sort((a, b) => b[1].last_msg_id - a[1].last_msg_id),
);
}
export function get() {
return get_sorted_topics();
}
function format_topic(topic_data) {
const last_msg = message_store.get(topic_data.last_msg_id);
const stream = last_msg.stream;
@ -650,10 +574,6 @@ export function complete_rerender() {
});
}
export function is_visible() {
return $("#recent_topics_view").is(":visible");
}
export function show() {
if (is_visible()) {
// If we're already visible, E.g. because the user hit Esc

View File

@ -0,0 +1,25 @@
import $ from "jquery";
import * as compose_state from "./compose_state";
import * as overlays from "./overlays";
import * as popovers from "./popovers";
export function is_visible() {
return $("#recent_topics_view").is(":visible");
}
export function is_in_focus() {
// Check if user is focused on
// recent topics.
return (
is_visible() &&
!compose_state.composing() &&
!popovers.any_active() &&
!overlays.is_active() &&
!$(".home-page-input").is(":focus")
);
}
export function get_topic_key(stream_id, topic) {
return stream_id + ":" + topic.toLowerCase();
}

View File

@ -9,7 +9,7 @@ import * as message_view_header from "./message_view_header";
import * as narrow_state from "./narrow_state";
import * as overlays from "./overlays";
import * as peer_data from "./peer_data";
import * as recent_topics from "./recent_topics";
import * as recent_topics_ui from "./recent_topics_ui";
import * as settings_notifications from "./settings_notifications";
import * as stream_color from "./stream_color";
import * as stream_data from "./stream_data";
@ -46,7 +46,7 @@ export function update_property(stream_id, property, value, other_values) {
break;
case "in_home_view":
stream_muting.update_is_muted(sub, !value);
recent_topics.complete_rerender();
recent_topics_ui.complete_rerender();
break;
case "desktop_notifications":
case "audible_notifications":

View File

@ -47,7 +47,7 @@ import * as people from "./people";
import * as pm_conversations from "./pm_conversations";
import * as presence from "./presence";
import * as realm_playground from "./realm_playground";
import * as recent_topics from "./recent_topics";
import * as recent_topics_util from "./recent_topics_util";
import * as reload from "./reload";
import * as resize from "./resize";
import * as rows from "./rows";
@ -146,7 +146,7 @@ export function initialize_kitchen_sink_stuff() {
message_viewport.message_pane.on("wheel", (e) => {
const delta = e.originalEvent.deltaY;
if (!overlays.is_active() && !recent_topics.is_visible()) {
if (!overlays.is_active() && !recent_topics_util.is_visible()) {
// In the message view, we use a throttled mousewheel handler.
throttled_mousewheelhandler(e, delta);
}

View File

@ -5,7 +5,7 @@ import * as message_lists from "./message_lists";
import * as message_store from "./message_store";
import * as message_viewport from "./message_viewport";
import * as notifications from "./notifications";
import * as recent_topics from "./recent_topics";
import * as recent_topics_ui from "./recent_topics_ui";
import * as reload from "./reload";
import * as unread from "./unread";
import * as unread_ui from "./unread_ui";
@ -36,7 +36,7 @@ function process_newly_read_message(message, options) {
message_list.narrowed.show_message_as_read(message, options);
}
notifications.close_notification(message);
recent_topics.update_topic_unread_count(message);
recent_topics_ui.update_topic_unread_count(message);
}
export function process_read_messages_event(message_ids) {

View File

@ -107,7 +107,8 @@ EXEMPT_FILES = {
"static/js/realm_icon.js",
"static/js/realm_logo.js",
"static/js/realm_playground.js",
"static/js/recent_topics.js",
"static/js/recent_topics_ui.js",
"static/js/recent_topics_util.js",
"static/js/reload.js",
"static/js/reminder.js",
"static/js/resize.js",