mirror of https://github.com/zulip/zulip.git
narrow: Use message list id to track message lists in DOM.
This removes use of zfilt and zhome from codebase.
This commit is contained in:
parent
91ee0bf676
commit
633f64a79e
|
@ -255,12 +255,7 @@
|
|||
<div id="loading_older_messages_indicator"></div>
|
||||
<div id="page_loading_indicator"></div>
|
||||
<div id="message_feed_errors_container"></div>
|
||||
<div id="message-lists-container">
|
||||
<div class="message-list focused-message-list" id="zhome" role="list" aria-live="polite" aria-label="{{ _('Messages') }}">
|
||||
</div>
|
||||
<div class="message-list" id="zfilt" role="list" aria-live="polite" aria-label="{{ _('Messages') }}">
|
||||
</div>
|
||||
</div>
|
||||
<div id="message-lists-container"></div>
|
||||
<div id="scheduled_message_indicator">
|
||||
</div>
|
||||
<div id="typing_notifications">
|
||||
|
|
|
@ -57,10 +57,14 @@ async function run() {
|
|||
await page.goto(`${options.realmUri}/#narrow/id/${options.messageId}`, {
|
||||
waitUntil: "networkidle2",
|
||||
});
|
||||
const messageSelector = `#zfilt${CSS.escape(options.messageId)}`;
|
||||
// eslint-disable-next-line no-undef
|
||||
const message_list_id = await page.evaluate(() => zulip_test.current_msg_list.id);
|
||||
const messageSelector = `#message-row-${message_list_id}-${CSS.escape(options.messageId)}`;
|
||||
await page.waitForSelector(messageSelector);
|
||||
// remove unread marker and don't select message
|
||||
const marker = `#zfilt${CSS.escape(options.messageId)} .unread_marker`;
|
||||
const marker = `#message-row-${message_list_id}-${CSS.escape(
|
||||
options.messageId,
|
||||
)} .unread_marker`;
|
||||
await page.evaluate((sel) => $(sel).remove(), marker);
|
||||
const messageBox = await page.$(messageSelector);
|
||||
await page.evaluate((msg) => $(msg).removeClass("selected_message"), messageSelector);
|
||||
|
|
|
@ -28,14 +28,14 @@ function get_message_selector(text: string): string {
|
|||
}
|
||||
|
||||
async function test_send_messages(page: Page): Promise<void> {
|
||||
const initial_msgs_count = (await page.$$("#zhome .message_row")).length;
|
||||
const initial_msgs_count = (await page.$$(".message-list .message_row")).length;
|
||||
|
||||
await common.send_multiple_messages(page, [
|
||||
{stream_name: "Verona", topic: "Reply test", content: "Compose stream reply test"},
|
||||
{recipient: "cordelia@zulip.com", content: "Compose direct message reply test"},
|
||||
]);
|
||||
|
||||
assert.equal((await page.$$("#zhome .message_row")).length, initial_msgs_count + 2);
|
||||
assert.equal((await page.$$(".message-list .message_row")).length, initial_msgs_count + 2);
|
||||
}
|
||||
|
||||
async function test_stream_compose_keyboard_shortcut(page: Page): Promise<void> {
|
||||
|
@ -138,7 +138,9 @@ async function test_send_multirecipient_pm_from_cordelia_pm_narrow(page: Page):
|
|||
// Go back to all messages view and make sure all messages are loaded.
|
||||
await page.click("#left-sidebar-navigation-list .top_left_all_messages");
|
||||
|
||||
await page.waitForSelector("#zhome .message_row", {visible: true});
|
||||
await page.waitForSelector(".message-list .message_row", {visible: true});
|
||||
// Assert that there is only one message list.
|
||||
assert.equal((await page.$$(".message-list")).length, 1);
|
||||
const pm = await page.waitForSelector(
|
||||
`xpath/(//*[${common.has_class_x(
|
||||
"messagebox",
|
||||
|
@ -217,7 +219,7 @@ async function test_markdown_preview(page: Page): Promise<void> {
|
|||
async function compose_tests(page: Page): Promise<void> {
|
||||
await common.log_in(page);
|
||||
await page.click("#left-sidebar-navigation-list .top_left_all_messages");
|
||||
await page.waitForSelector("#zhome .message_row", {visible: true});
|
||||
await page.waitForSelector(".message-list .message_row", {visible: true});
|
||||
await test_send_messages(page);
|
||||
await test_keyboard_shortcuts(page);
|
||||
await test_reply_by_click_prepopulates_stream_topic_names(page);
|
||||
|
|
|
@ -12,7 +12,7 @@ async function copy_messages(
|
|||
return await page.evaluate(
|
||||
(start_message: string, end_message: string) => {
|
||||
function get_message_node(message: string): Element {
|
||||
return [...document.querySelectorAll("#zhome .message_content")].find(
|
||||
return [...document.querySelectorAll(".message-list .message_content")].find(
|
||||
(node) => node.textContent?.trim() === message,
|
||||
)!;
|
||||
}
|
||||
|
@ -130,7 +130,9 @@ async function test_copying_messages_from_several_topics(page: Page): Promise<vo
|
|||
async function copy_paste_test(page: Page): Promise<void> {
|
||||
await common.log_in(page);
|
||||
await page.click("#left-sidebar-navigation-list .top_left_all_messages");
|
||||
await page.waitForSelector("#zhome .message_row", {visible: true});
|
||||
await page.waitForSelector(".message-list .message_row", {visible: true});
|
||||
// Assert that there is only one message list.
|
||||
assert.equal((await page.$$(".message-list")).length, 1);
|
||||
|
||||
await common.send_multiple_messages(page, [
|
||||
{stream_name: "Verona", topic: "copy-paste-topic #1", content: "copy paste test A"},
|
||||
|
@ -148,7 +150,8 @@ async function copy_paste_test(page: Page): Promise<void> {
|
|||
{stream_name: "Verona", topic: "copy-paste-topic #3", content: "copy paste test G"},
|
||||
]);
|
||||
|
||||
await common.check_messages_sent(page, "zhome", [
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await common.check_messages_sent(page, message_list_id, [
|
||||
["Verona > copy-paste-topic #1", ["copy paste test A", "copy paste test B"]],
|
||||
[
|
||||
"Verona > copy-paste-topic #2",
|
||||
|
|
|
@ -5,7 +5,7 @@ import type {Page} from "puppeteer";
|
|||
import * as common from "./lib/common";
|
||||
|
||||
async function click_delete_and_return_last_msg_id(page: Page): Promise<string> {
|
||||
const msg = (await page.$$("#zhome .message_row")).at(-1);
|
||||
const msg = (await page.$$(".message-list .message_row")).at(-1);
|
||||
assert.ok(msg !== undefined);
|
||||
const id = await (await msg.getProperty("id")).jsonValue();
|
||||
await msg.hover();
|
||||
|
@ -23,8 +23,14 @@ async function click_delete_and_return_last_msg_id(page: Page): Promise<string>
|
|||
async function delete_message_test(page: Page): Promise<void> {
|
||||
await common.log_in(page);
|
||||
await page.click("#left-sidebar-navigation-list .top_left_all_messages");
|
||||
await page.waitForSelector("#zhome .message_row", {visible: true});
|
||||
const messages_quantity = (await page.$$("#zhome .message_row")).length;
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await page.waitForSelector(
|
||||
`.message-list[data-message-list-id='${message_list_id}'] .message_row`,
|
||||
{visible: true},
|
||||
);
|
||||
// Assert that there is only one message list.
|
||||
assert.equal((await page.$$(".message-list")).length, 1);
|
||||
const messages_quantity = (await page.$$(".message-list .message_row")).length;
|
||||
const last_message_id = await click_delete_and_return_last_msg_id(page);
|
||||
|
||||
await common.wait_for_micromodal_to_open(page);
|
||||
|
@ -34,7 +40,7 @@ async function delete_message_test(page: Page): Promise<void> {
|
|||
await common.wait_for_micromodal_to_close(page);
|
||||
|
||||
await page.waitForSelector(`#${CSS.escape(last_message_id)}`, {hidden: true});
|
||||
assert.equal((await page.$$("#zhome .message_row")).length, messages_quantity - 1);
|
||||
assert.equal((await page.$$(".message-list .message_row")).length, messages_quantity - 1);
|
||||
}
|
||||
|
||||
common.run_test(delete_message_test);
|
||||
|
|
|
@ -246,7 +246,9 @@ async function test_save_draft_by_reloading(page: Page): Promise<void> {
|
|||
async function drafts_test(page: Page): Promise<void> {
|
||||
await common.log_in(page);
|
||||
await page.click("#left-sidebar-navigation-list .top_left_all_messages");
|
||||
await page.waitForSelector("#zhome .message_row", {visible: true});
|
||||
await page.waitForSelector(".message-list .message_row", {visible: true});
|
||||
// Assert that there is only one message list.
|
||||
assert.equal((await page.$$(".message-list")).length, 1);
|
||||
|
||||
await test_empty_drafts(page);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import type {Page} from "puppeteer";
|
|||
import * as common from "./lib/common";
|
||||
|
||||
async function trigger_edit_last_message(page: Page): Promise<void> {
|
||||
const msg = (await page.$$("#zhome .message_row")).at(-1);
|
||||
const msg = (await page.$$(".message-list .message_row")).at(-1);
|
||||
assert.ok(msg !== undefined);
|
||||
const id = await (await msg.getProperty("id")).jsonValue();
|
||||
await msg.hover();
|
||||
|
@ -29,7 +29,7 @@ async function edit_stream_message(page: Page, content: string): Promise<void> {
|
|||
await common.wait_for_fully_processed_message(page, content);
|
||||
}
|
||||
|
||||
async function test_stream_message_edit(page: Page): Promise<void> {
|
||||
async function test_stream_message_edit(page: Page, message_list_id: number): Promise<void> {
|
||||
await common.send_message(page, "stream", {
|
||||
stream_name: "Verona",
|
||||
topic: "edits",
|
||||
|
@ -38,11 +38,13 @@ async function test_stream_message_edit(page: Page): Promise<void> {
|
|||
|
||||
await edit_stream_message(page, "test edited");
|
||||
|
||||
await common.check_messages_sent(page, "zhome", [["Verona > edits", ["test edited"]]]);
|
||||
await common.check_messages_sent(page, message_list_id, [["Verona > edits", ["test edited"]]]);
|
||||
}
|
||||
|
||||
async function test_edit_message_with_slash_me(page: Page): Promise<void> {
|
||||
const last_message_xpath = `(//*[@id="zhome"]//*[${common.has_class_x("messagebox")}])[last()]`;
|
||||
const last_message_xpath = `(//*[${common.has_class_x("message-list")}]//*[${common.has_class_x(
|
||||
"messagebox",
|
||||
)}])[last()]`;
|
||||
|
||||
await common.send_message(page, "stream", {
|
||||
stream_name: "Verona",
|
||||
|
@ -74,7 +76,7 @@ async function test_edit_message_with_slash_me(page: Page): Promise<void> {
|
|||
);
|
||||
}
|
||||
|
||||
async function test_edit_private_message(page: Page): Promise<void> {
|
||||
async function test_edit_private_message(page: Page, message_list_id: number): Promise<void> {
|
||||
await common.send_message(page, "private", {
|
||||
recipient: "cordelia@zulip.com",
|
||||
content: "test editing pm",
|
||||
|
@ -85,7 +87,7 @@ async function test_edit_private_message(page: Page): Promise<void> {
|
|||
await page.click(".message_edit_save");
|
||||
await common.wait_for_fully_processed_message(page, "test edited pm");
|
||||
|
||||
await common.check_messages_sent(page, "zhome", [
|
||||
await common.check_messages_sent(page, message_list_id, [
|
||||
["You and Cordelia, Lear's daughter", ["test edited pm"]],
|
||||
]);
|
||||
}
|
||||
|
@ -93,11 +95,12 @@ async function test_edit_private_message(page: Page): Promise<void> {
|
|||
async function edit_tests(page: Page): Promise<void> {
|
||||
await common.log_in(page);
|
||||
await page.click("#left-sidebar-navigation-list .top_left_all_messages");
|
||||
await page.waitForSelector("#zhome .message_row", {visible: true});
|
||||
await page.waitForSelector(".message-list .message_row", {visible: true});
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
|
||||
await test_stream_message_edit(page);
|
||||
await test_stream_message_edit(page, message_list_id);
|
||||
await test_edit_message_with_slash_me(page);
|
||||
await test_edit_private_message(page);
|
||||
await test_edit_private_message(page, message_list_id);
|
||||
}
|
||||
|
||||
common.run_test(edit_tests);
|
||||
|
|
|
@ -26,6 +26,8 @@ export const is_firefox = process.env.PUPPETEER_PRODUCT === "firefox";
|
|||
let realm_url = "http://zulip.zulipdev.com:9981/";
|
||||
const gps = new StackTraceGPS({ajax: async (url) => (await fetch(url)).text()});
|
||||
|
||||
let last_current_msg_list_id: number | null = null;
|
||||
|
||||
export const pm_recipient = {
|
||||
async set(page: Page, recipient: string): Promise<void> {
|
||||
// Without using the delay option here there seems to be
|
||||
|
@ -483,9 +485,11 @@ export async function send_multiple_messages(page: Page, msgs: Message[]): Promi
|
|||
*/
|
||||
export async function get_rendered_messages(
|
||||
page: Page,
|
||||
table = "zhome",
|
||||
message_list_id: number,
|
||||
): Promise<[string, string[]][]> {
|
||||
const recipient_rows = await page.$$(`#${CSS.escape(table)} .recipient_row`);
|
||||
const recipient_rows = await page.$$(
|
||||
`.message-list[data-message-list-id='${message_list_id}'] .recipient_row`,
|
||||
);
|
||||
return Promise.all(
|
||||
recipient_rows.map(async (element): Promise<[string, string[]]> => {
|
||||
const stream_label = await element.$(".stream_label");
|
||||
|
@ -519,11 +523,13 @@ export async function get_rendered_messages(
|
|||
// messages array passed exist in the order they are passed.
|
||||
export async function check_messages_sent(
|
||||
page: Page,
|
||||
table: string,
|
||||
message_list_id: number,
|
||||
messages: [string, string[]][],
|
||||
): Promise<void> {
|
||||
await page.waitForSelector(`#${CSS.escape(table)}`, {visible: true});
|
||||
const rendered_messages = await get_rendered_messages(page, table);
|
||||
await page.waitForSelector(`.message-list[data-message-list-id='${message_list_id}']`, {
|
||||
visible: true,
|
||||
});
|
||||
const rendered_messages = await get_rendered_messages(page, message_list_id);
|
||||
|
||||
// We only check the last n messages because if we run
|
||||
// the test with --interactive there will be duplicates.
|
||||
|
@ -714,3 +720,23 @@ export function run_test(test_function: (page: Page) => Promise<void>): void {
|
|||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
export async function get_current_msg_list_id(
|
||||
page: Page,
|
||||
wait_for_change = false,
|
||||
): Promise<number> {
|
||||
if (wait_for_change) {
|
||||
// Wait for the current_msg_list to change if the in the middle of switching narrows.
|
||||
// Also works as a way to verify that the current message list did change.
|
||||
// NOTE: This only checks if the current message list id changed from the last call to this function,
|
||||
// so, make sure to have a call to this function before changing to the narrow that you want to check.
|
||||
await page.waitForFunction(
|
||||
(last_current_msg_list_id) =>
|
||||
zulip_test.current_msg_list.id !== last_current_msg_list_id,
|
||||
{},
|
||||
last_current_msg_list_id,
|
||||
);
|
||||
}
|
||||
last_current_msg_list_id = await page.evaluate(() => zulip_test.current_msg_list.id);
|
||||
return last_current_msg_list_id!;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import * as common from "./lib/common";
|
|||
async function test_mention(page: Page): Promise<void> {
|
||||
await common.log_in(page);
|
||||
await page.click("#left-sidebar-navigation-list .top_left_all_messages");
|
||||
await page.waitForSelector("#zhome .message_row", {visible: true});
|
||||
await page.waitForSelector(".message-list .message_row", {visible: true});
|
||||
await page.keyboard.press("KeyC");
|
||||
await page.waitForSelector("#compose", {visible: true});
|
||||
|
||||
|
@ -36,7 +36,10 @@ async function test_mention(page: Page): Promise<void> {
|
|||
await page.click("#compose_banners .wildcard_warning .main-view-banner-action-button");
|
||||
await page.waitForSelector(".wildcard_warning", {hidden: true});
|
||||
|
||||
await common.check_messages_sent(page, "zhome", [["Verona > Test mention all", ["@all"]]]);
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await common.check_messages_sent(page, message_list_id, [
|
||||
["Verona > Test mention all", ["@all"]],
|
||||
]);
|
||||
}
|
||||
|
||||
common.run_test(test_mention);
|
||||
|
|
|
@ -10,7 +10,8 @@ async function get_stream_li(page: Page, stream_name: string): Promise<string> {
|
|||
}
|
||||
|
||||
async function expect_home(page: Page): Promise<void> {
|
||||
await common.check_messages_sent(page, "zhome", [
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await common.check_messages_sent(page, message_list_id, [
|
||||
["Verona > test", ["verona test a", "verona test b"]],
|
||||
["Verona > other topic", ["verona other topic c"]],
|
||||
["Denmark > test", ["denmark message"]],
|
||||
|
@ -26,8 +27,11 @@ async function expect_home(page: Page): Promise<void> {
|
|||
}
|
||||
|
||||
async function expect_verona_stream(page: Page): Promise<void> {
|
||||
await page.waitForSelector("#zfilt", {visible: true});
|
||||
await common.check_messages_sent(page, "zfilt", [
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await page.waitForSelector(`.message-list[data-message-list-id='${message_list_id}']`, {
|
||||
visible: true,
|
||||
});
|
||||
await common.check_messages_sent(page, message_list_id, [
|
||||
["Verona > test", ["verona test a", "verona test b"]],
|
||||
["Verona > other topic", ["verona other topic c"]],
|
||||
["Verona > test", ["verona test d"]],
|
||||
|
@ -36,8 +40,11 @@ async function expect_verona_stream(page: Page): Promise<void> {
|
|||
}
|
||||
|
||||
async function expect_verona_stream_test_topic(page: Page): Promise<void> {
|
||||
await page.waitForSelector("#zfilt", {visible: true});
|
||||
await common.check_messages_sent(page, "zfilt", [
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await page.waitForSelector(`.message-list[data-message-list-id='${message_list_id}']`, {
|
||||
visible: true,
|
||||
});
|
||||
await common.check_messages_sent(page, message_list_id, [
|
||||
["Verona > test", ["verona test a", "verona test b", "verona test d"]],
|
||||
]);
|
||||
assert.strictEqual(
|
||||
|
@ -47,15 +54,21 @@ async function expect_verona_stream_test_topic(page: Page): Promise<void> {
|
|||
}
|
||||
|
||||
async function expect_verona_other_topic(page: Page): Promise<void> {
|
||||
await page.waitForSelector("#zfilt", {visible: true});
|
||||
await common.check_messages_sent(page, "zfilt", [
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await page.waitForSelector(`.message-list[data-message-list-id='${message_list_id}']`, {
|
||||
visible: true,
|
||||
});
|
||||
await common.check_messages_sent(page, message_list_id, [
|
||||
["Verona > other topic", ["verona other topic c"]],
|
||||
]);
|
||||
}
|
||||
|
||||
async function expect_test_topic(page: Page): Promise<void> {
|
||||
await page.waitForSelector("#zfilt", {visible: true});
|
||||
await common.check_messages_sent(page, "zfilt", [
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await page.waitForSelector(`.message-list[data-message-list-id='${message_list_id}']`, {
|
||||
visible: true,
|
||||
});
|
||||
await common.check_messages_sent(page, message_list_id, [
|
||||
["Verona > test", ["verona test a", "verona test b"]],
|
||||
["Denmark > test", ["denmark message"]],
|
||||
["Verona > test", ["verona test d"]],
|
||||
|
@ -63,8 +76,11 @@ async function expect_test_topic(page: Page): Promise<void> {
|
|||
}
|
||||
|
||||
async function expect_group_direct_messages(page: Page): Promise<void> {
|
||||
await page.waitForSelector("#zfilt", {visible: true});
|
||||
await common.check_messages_sent(page, "zfilt", [
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await page.waitForSelector(`.message-list[data-message-list-id='${message_list_id}']`, {
|
||||
visible: true,
|
||||
});
|
||||
await common.check_messages_sent(page, message_list_id, [
|
||||
[
|
||||
"You and Cordelia, Lear's daughter, King Hamlet",
|
||||
["group direct message a", "group direct message b", "group direct message d"],
|
||||
|
@ -77,8 +93,11 @@ async function expect_group_direct_messages(page: Page): Promise<void> {
|
|||
}
|
||||
|
||||
async function expect_cordelia_direct_messages(page: Page): Promise<void> {
|
||||
await page.waitForSelector("#zfilt", {visible: true});
|
||||
await common.check_messages_sent(page, "zfilt", [
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await page.waitForSelector(`.message-list[data-message-list-id='${message_list_id}']`, {
|
||||
visible: true,
|
||||
});
|
||||
await common.check_messages_sent(page, message_list_id, [
|
||||
["You and Cordelia, Lear's daughter", ["direct message c", "direct message e"]],
|
||||
]);
|
||||
}
|
||||
|
@ -88,7 +107,9 @@ async function un_narrow(page: Page): Promise<void> {
|
|||
await page.keyboard.press("Escape");
|
||||
}
|
||||
await page.click("#left-sidebar-navigation-list .top_left_all_messages");
|
||||
await page.waitForSelector("#zhome .message_row", {visible: true});
|
||||
await page.waitForSelector(".message-list .message_row", {visible: true});
|
||||
// Assert that there is only one message list.
|
||||
assert.equal((await page.$$(".message-list")).length, 1);
|
||||
assert.strictEqual(await page.title(), "All messages - Zulip Dev - Zulip");
|
||||
}
|
||||
|
||||
|
@ -104,7 +125,7 @@ async function expect_recent_view(page: Page): Promise<void> {
|
|||
async function test_navigations_from_home(page: Page): Promise<void> {
|
||||
return; // No idea why this is broken.
|
||||
console.log("Narrowing by clicking stream");
|
||||
await page.click(`#zhome [title='Narrow to stream "Verona"']`);
|
||||
await page.click(`.focused-message-list [title='Narrow to stream "Verona"']`);
|
||||
await expect_verona_stream(page);
|
||||
|
||||
assert.strictEqual(await page.title(), "#Verona - Zulip Dev - Zulip");
|
||||
|
@ -112,7 +133,7 @@ async function test_navigations_from_home(page: Page): Promise<void> {
|
|||
await expect_home(page);
|
||||
|
||||
console.log("Narrowing by clicking topic");
|
||||
await page.click(`#zhome [title='Narrow to stream "Verona", topic "test"']`);
|
||||
await page.click(`.focused-message-list [title='Narrow to stream "Verona", topic "test"']`);
|
||||
await expect_verona_stream_test_topic(page);
|
||||
|
||||
await un_narrow(page);
|
||||
|
@ -121,7 +142,7 @@ async function test_navigations_from_home(page: Page): Promise<void> {
|
|||
return; // TODO: rest of this test seems nondeterministically broken
|
||||
console.log("Narrowing by clicking group personal header");
|
||||
await page.click(
|
||||
`#zhome [title="Narrow to your direct messages with Cordelia, Lear's daughter, King Hamlet"]`,
|
||||
`.focused-message-list [title="Narrow to your direct messages with Cordelia, Lear's daughter, King Hamlet"]`,
|
||||
);
|
||||
await expect_group_direct_messages(page);
|
||||
|
||||
|
@ -129,7 +150,7 @@ async function test_navigations_from_home(page: Page): Promise<void> {
|
|||
await expect_home(page);
|
||||
|
||||
await page.click(
|
||||
`#zhome [title="Narrow to your direct messages with Cordelia, Lear's daughter, King Hamlet"]`,
|
||||
`.focused-message-list [title="Narrow to your direct messages with Cordelia, Lear's daughter, King Hamlet"]`,
|
||||
);
|
||||
await un_narrow_by_clicking_org_icon(page);
|
||||
await expect_recent_view(page);
|
||||
|
@ -161,11 +182,13 @@ async function search_silent_user(page: Page, str: string, item: string): Promis
|
|||
await common.get_text_from_selector(page, ".empty_feed_notice"),
|
||||
expect_message,
|
||||
);
|
||||
await common.get_current_msg_list_id(page, true);
|
||||
await un_narrow(page);
|
||||
await expect_home(page);
|
||||
}
|
||||
|
||||
async function expect_non_existing_user(page: Page): Promise<void> {
|
||||
await common.get_current_msg_list_id(page, true);
|
||||
await page.waitForSelector(".empty_feed_notice", {visible: true});
|
||||
const expected_message = "This user does not exist!";
|
||||
assert.strictEqual(
|
||||
|
@ -175,6 +198,7 @@ async function expect_non_existing_user(page: Page): Promise<void> {
|
|||
}
|
||||
|
||||
async function expect_non_existing_users(page: Page): Promise<void> {
|
||||
await common.get_current_msg_list_id(page, true);
|
||||
await page.waitForSelector(".empty_feed_notice", {visible: true});
|
||||
const expected_message = "One or more of these users do not exist!";
|
||||
assert.strictEqual(
|
||||
|
@ -263,8 +287,11 @@ async function search_tests(page: Page): Promise<void> {
|
|||
}
|
||||
|
||||
async function expect_all_direct_messages(page: Page): Promise<void> {
|
||||
await page.waitForSelector("#zfilt", {visible: true});
|
||||
await common.check_messages_sent(page, "zfilt", [
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await page.waitForSelector(`.message-list[data-message-list-id='${message_list_id}']`, {
|
||||
visible: true,
|
||||
});
|
||||
await common.check_messages_sent(page, message_list_id, [
|
||||
[
|
||||
"You and Cordelia, Lear's daughter, King Hamlet",
|
||||
["group direct message a", "group direct message b"],
|
||||
|
@ -477,18 +504,34 @@ async function test_narrow_public_streams(page: Page): Promise<void> {
|
|||
await page.click(".subscriptions-header .exit-sign");
|
||||
await page.waitForSelector("#subscription_overlay", {hidden: true});
|
||||
await page.goto(`http://zulip.zulipdev.com:9981/#narrow/stream/${stream_id}-Denmark`);
|
||||
await page.waitForSelector("#zfilt .recipient_row ~ .recipient_row ~ .recipient_row");
|
||||
assert.ok((await page.$("#zfilt .stream-status")) !== null);
|
||||
let message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await page.waitForSelector(
|
||||
`.message-list[data-message-list-id='${message_list_id}'] .recipient_row ~ .recipient_row ~ .recipient_row`,
|
||||
);
|
||||
assert.ok(
|
||||
(await page.$(
|
||||
`.message-list[data-message-list-id='${message_list_id}'] .stream-status`,
|
||||
)) !== null,
|
||||
);
|
||||
|
||||
await page.goto("http://zulip.zulipdev.com:9981/#narrow/streams/public");
|
||||
await page.waitForSelector("#zfilt .recipient_row ~ .recipient_row ~ .recipient_row");
|
||||
assert.ok((await page.$("#zfilt .stream-status")) === null);
|
||||
message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await page.waitForSelector(
|
||||
`.message-list[data-message-list-id='${message_list_id}'] .recipient_row ~ .recipient_row ~ .recipient_row`,
|
||||
);
|
||||
assert.ok(
|
||||
(await page.$(
|
||||
`.message-list[data-message-list-id='${message_list_id}'] .stream-status`,
|
||||
)) === null,
|
||||
);
|
||||
}
|
||||
|
||||
async function message_basic_tests(page: Page): Promise<void> {
|
||||
await common.log_in(page);
|
||||
await page.click("#left-sidebar-navigation-list .top_left_all_messages");
|
||||
await page.waitForSelector("#zhome .message_row", {visible: true});
|
||||
await page.waitForSelector(".message-list .message_row", {visible: true});
|
||||
// Assert that there is only one message list.
|
||||
assert.equal((await page.$$(".message-list")).length, 1);
|
||||
|
||||
console.log("Sending messages");
|
||||
await common.send_multiple_messages(page, [
|
||||
|
|
|
@ -71,7 +71,10 @@ async function test_reload_hash(page: Page): Promise<void> {
|
|||
|
||||
await page.evaluate(() => zulip_test.initiate_reload({immediate: true}));
|
||||
await page.waitForNavigation();
|
||||
await page.waitForSelector("#zfilt", {visible: true});
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await page.waitForSelector(`.message-list[data-message-list-id='${message_list_id}']`, {
|
||||
visible: true,
|
||||
});
|
||||
|
||||
const page_load_time = await page.evaluate(() => zulip_test.page_load_time);
|
||||
assert.ok(page_load_time > initial_page_load_time, "Page not reloaded.");
|
||||
|
|
|
@ -7,12 +7,12 @@ import * as common from "./lib/common";
|
|||
const message = "test star";
|
||||
|
||||
async function stars_count(page: Page): Promise<number> {
|
||||
return (await page.$$("#zhome .zulip-icon-star-filled:not(.empty-star)")).length;
|
||||
return (await page.$$(".message-list .zulip-icon-star-filled:not(.empty-star)")).length;
|
||||
}
|
||||
|
||||
async function toggle_test_star_message(page: Page): Promise<void> {
|
||||
const messagebox = await page.waitForSelector(
|
||||
`xpath/(//*[@id="zhome"]//*[${common.has_class_x(
|
||||
`xpath/(//*[${common.has_class_x("message-list")}]//*[${common.has_class_x(
|
||||
"message_content",
|
||||
)} and normalize-space()="${message}"])[last()]/ancestor::*[${common.has_class_x(
|
||||
"messagebox",
|
||||
|
@ -29,17 +29,24 @@ async function toggle_test_star_message(page: Page): Promise<void> {
|
|||
|
||||
async function test_narrow_to_starred_messages(page: Page): Promise<void> {
|
||||
await page.click('#left-sidebar-navigation-list a[href^="#narrow/is/starred"]');
|
||||
await common.check_messages_sent(page, "zfilt", [["Verona > stars", [message]]]);
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await common.check_messages_sent(page, message_list_id, [["Verona > stars", [message]]]);
|
||||
|
||||
// Go back to all messages narrow.
|
||||
await page.click("#left-sidebar-navigation-list .top_left_all_messages");
|
||||
await page.waitForSelector("#zhome .message_row", {visible: true});
|
||||
await page.waitForSelector(".message-list .message_row", {visible: true});
|
||||
}
|
||||
|
||||
async function stars_test(page: Page): Promise<void> {
|
||||
await common.log_in(page);
|
||||
await page.click("#left-sidebar-navigation-list .top_left_all_messages");
|
||||
await page.waitForSelector("#zhome .message_row", {visible: true});
|
||||
const message_list_id = await common.get_current_msg_list_id(page, true);
|
||||
await page.waitForSelector(
|
||||
`.message-list[data-message-list-id='${message_list_id}'] .message_row`,
|
||||
{visible: true},
|
||||
);
|
||||
// Assert that there is only one message list.
|
||||
assert.equal((await page.$$(".message-list")).length, 1);
|
||||
await common.send_message(page, "stream", {
|
||||
stream_name: "Verona",
|
||||
topic: "stars",
|
||||
|
@ -49,7 +56,10 @@ async function stars_test(page: Page): Promise<void> {
|
|||
assert.strictEqual(await stars_count(page), 0, "Unexpected already starred message(s).");
|
||||
|
||||
await toggle_test_star_message(page);
|
||||
await page.waitForSelector("#zhome .zulip-icon-star-filled", {visible: true});
|
||||
await page.waitForSelector(
|
||||
`.message-list[data-message-list-id='${message_list_id}'] .zulip-icon-star-filled`,
|
||||
{visible: true},
|
||||
);
|
||||
assert.strictEqual(
|
||||
await stars_count(page),
|
||||
1,
|
||||
|
|
|
@ -42,8 +42,7 @@ export function set_focused_recipient(msg_type) {
|
|||
}
|
||||
|
||||
function display_messages_normally() {
|
||||
const $table = rows.get_table(message_lists.current.table_name);
|
||||
$table.find(".recipient_row").removeClass("message-fade");
|
||||
message_lists.current.view.$list.find(".recipient_row").removeClass("message-fade");
|
||||
|
||||
normal_display = true;
|
||||
}
|
||||
|
@ -77,9 +76,7 @@ function fade_messages() {
|
|||
// Defer updating all message groups so that the compose box can open sooner
|
||||
setTimeout(
|
||||
(expected_msg_list, expected_recipient) => {
|
||||
const all_groups = rows
|
||||
.get_table(message_lists.current.table_name)
|
||||
.find(".recipient_row");
|
||||
const $all_groups = message_lists.current.view.$list.find(".recipient_row");
|
||||
|
||||
if (
|
||||
message_lists.current !== expected_msg_list ||
|
||||
|
@ -93,8 +90,8 @@ function fade_messages() {
|
|||
|
||||
// Note: The below algorithm relies on the fact that all_elts is
|
||||
// sorted as it would be displayed in the message view
|
||||
for (i = 0; i < all_groups.length; i += 1) {
|
||||
const $group_elt = $(all_groups[i]);
|
||||
for (i = 0; i < $all_groups.length; i += 1) {
|
||||
const $group_elt = $($all_groups[i]);
|
||||
should_fade_group = compose_fade_helper.should_fade_message(
|
||||
rows.recipient_from_group($group_elt),
|
||||
);
|
||||
|
|
|
@ -17,6 +17,7 @@ import * as stream_data from "./stream_data";
|
|||
import {user_settings} from "./user_settings";
|
||||
|
||||
export class MessageList {
|
||||
static id_counter = 0;
|
||||
// A MessageList is the main interface for a message feed that is
|
||||
// rendered in the DOM. Code outside the message feed rendering
|
||||
// internals will directly call this module in order to manipulate
|
||||
|
@ -30,6 +31,8 @@ export class MessageList {
|
|||
// is not particularly well-defined; it could be nice to figure
|
||||
// out a good rule.
|
||||
constructor(opts) {
|
||||
MessageList.id_counter += 1;
|
||||
this.id = MessageList.id_counter;
|
||||
// The MessageListData keeps track of the actual sequence of
|
||||
// messages displayed by this MessageList. Most
|
||||
// configuration/logic questions in this module will be
|
||||
|
@ -46,11 +49,6 @@ export class MessageList {
|
|||
});
|
||||
}
|
||||
|
||||
// The table_name is the outer HTML element for this message
|
||||
// list in the DOM.
|
||||
const table_name = opts.table_name;
|
||||
this.table_name = table_name;
|
||||
|
||||
// TODO: This property should likely just be inlined into
|
||||
// having the MessageListView code that needs to access it
|
||||
// query .data.filter directly.
|
||||
|
@ -59,7 +57,7 @@ export class MessageList {
|
|||
// The MessageListView object that is responsible for
|
||||
// maintaining this message feed's HTML representation in the
|
||||
// DOM.
|
||||
this.view = new MessageListView(this, table_name, collapse_messages);
|
||||
this.view = new MessageListView(this, collapse_messages, opts.is_node_test);
|
||||
|
||||
// Whether this is a narrowed message list. The only message
|
||||
// list that is not is the home_msg_list global.
|
||||
|
@ -266,7 +264,7 @@ export class MessageList {
|
|||
// false.
|
||||
if (!opts.use_closest && closest_id !== id) {
|
||||
error_data = {
|
||||
table_name: this.table_name,
|
||||
filter_terms: this.filter.terms(),
|
||||
id,
|
||||
closest_id,
|
||||
};
|
||||
|
@ -275,7 +273,7 @@ export class MessageList {
|
|||
|
||||
if (closest_id === -1 && !opts.empty_ok) {
|
||||
error_data = {
|
||||
table_name: this.table_name,
|
||||
filter_terms: this.filter.terms(),
|
||||
id,
|
||||
items_length: this.data.num_items(),
|
||||
};
|
||||
|
@ -526,7 +524,6 @@ export class MessageList {
|
|||
export function initialize() {
|
||||
/* Create home_msg_list and register it. */
|
||||
const home_msg_list = new MessageList({
|
||||
table_name: "zhome",
|
||||
filter: new Filter([{operator: "in", operand: "home"}]),
|
||||
excludes_muted_topics: true,
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@ import * as resolved_topic from "../shared/src/resolved_topic";
|
|||
import render_bookend from "../templates/bookend.hbs";
|
||||
import render_login_to_view_image_button from "../templates/login_to_view_image_button.hbs";
|
||||
import render_message_group from "../templates/message_group.hbs";
|
||||
import render_message_list from "../templates/message_list.hbs";
|
||||
import render_recipient_row from "../templates/recipient_row.hbs";
|
||||
import render_single_message from "../templates/single_message.hbs";
|
||||
|
||||
|
@ -260,9 +261,12 @@ export class MessageListView {
|
|||
// Logic to compute context, render templates, insert them into
|
||||
// the DOM, and generally
|
||||
|
||||
constructor(list, table_name, collapse_messages) {
|
||||
constructor(list, collapse_messages, is_node_test = false) {
|
||||
// The MessageList that this MessageListView is responsible for rendering.
|
||||
this.list = list;
|
||||
this._add_message_list_to_DOM();
|
||||
// The jQuery element for the rendered list element.
|
||||
this.$list = $(`.message-list[data-message-list-id="${this.list.id}"]`);
|
||||
|
||||
// TODO: Access this via .list.data.
|
||||
this.collapse_messages = collapse_messages;
|
||||
|
@ -285,12 +289,10 @@ export class MessageListView {
|
|||
this.message_containers = new Map();
|
||||
this._message_groups = [];
|
||||
|
||||
// TODO: Should this be just accessing .list.table_name?
|
||||
this.table_name = table_name;
|
||||
if (this.table_name) {
|
||||
if (!is_node_test) {
|
||||
// Skip running this in node tests.
|
||||
this.clear_table();
|
||||
}
|
||||
|
||||
// For performance reasons, this module renders at most
|
||||
// _RENDER_WINDOW_SIZE messages into the DOM at a time, and
|
||||
// will transparently adjust which messages are rendered
|
||||
|
@ -312,6 +314,10 @@ export class MessageListView {
|
|||
// trigger a re-render
|
||||
_RENDER_THRESHOLD = 50;
|
||||
|
||||
_add_message_list_to_DOM() {
|
||||
$("#message-lists-container").append(render_message_list({message_list_id: this.list.id}));
|
||||
}
|
||||
|
||||
_get_msg_timestring(message_container) {
|
||||
let last_edit_timestamp;
|
||||
if (message_container.msg.local_edit_timestamp !== undefined) {
|
||||
|
@ -782,7 +788,7 @@ export class MessageListView {
|
|||
message_container.msg.message_reactions = msg_reactions;
|
||||
const msg_to_render = {
|
||||
...message_container,
|
||||
table_name: this.table_name,
|
||||
message_list_id: this.list.id,
|
||||
};
|
||||
return render_single_message(msg_to_render);
|
||||
}
|
||||
|
@ -790,13 +796,12 @@ export class MessageListView {
|
|||
_render_group(opts) {
|
||||
const message_groups = opts.message_groups;
|
||||
const use_match_properties = opts.use_match_properties;
|
||||
const table_name = opts.table_name;
|
||||
|
||||
return $(
|
||||
render_message_group({
|
||||
message_groups,
|
||||
use_match_properties,
|
||||
table_name,
|
||||
message_list_id: this.list.id,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
@ -810,8 +815,6 @@ export class MessageListView {
|
|||
}
|
||||
|
||||
const list = this.list; // for convenience
|
||||
const table_name = this.table_name;
|
||||
const $table = rows.get_table(table_name);
|
||||
let orig_scrolltop_offset;
|
||||
|
||||
// If we start with the message feed scrolled up (i.e.
|
||||
|
@ -857,7 +860,7 @@ export class MessageListView {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
const new_message_groups = this.build_message_groups(message_containers, this.table_name);
|
||||
const new_message_groups = this.build_message_groups(message_containers);
|
||||
const message_actions = this.merge_message_groups(new_message_groups, where);
|
||||
const new_dom_elements = [];
|
||||
let $rendered_groups;
|
||||
|
@ -876,7 +879,6 @@ export class MessageListView {
|
|||
$rendered_groups = this._render_group({
|
||||
message_groups: message_actions.prepend_groups,
|
||||
use_match_properties: this.list.is_keyword_search(),
|
||||
table_name: this.table_name,
|
||||
});
|
||||
|
||||
$dom_messages = $rendered_groups.find(".message_row");
|
||||
|
@ -886,8 +888,8 @@ export class MessageListView {
|
|||
|
||||
// The date row will be included in the message groups or will be
|
||||
// added in a rerendered in the group below
|
||||
$table.find(".recipient_row").first().prev(".date_row").remove();
|
||||
$table.prepend($rendered_groups);
|
||||
this.$list.find(".recipient_row").first().prev(".date_row").remove();
|
||||
this.$list.prepend($rendered_groups);
|
||||
condense.condense_and_collapse($dom_messages);
|
||||
}
|
||||
|
||||
|
@ -903,7 +905,6 @@ export class MessageListView {
|
|||
$rendered_groups = this._render_group({
|
||||
message_groups: [message_group],
|
||||
use_match_properties: this.list.is_keyword_search(),
|
||||
table_name: this.table_name,
|
||||
});
|
||||
|
||||
$dom_messages = $rendered_groups.find(".message_row");
|
||||
|
@ -917,7 +918,7 @@ export class MessageListView {
|
|||
|
||||
// Insert new messages in to the last message group
|
||||
if (message_actions.append_messages.length > 0) {
|
||||
$last_message_row = $table.find(".message_row").last().expectOne();
|
||||
$last_message_row = this.$list.find(".message_row").last().expectOne();
|
||||
$last_group_row = rows.get_message_recipient_row($last_message_row);
|
||||
$dom_messages = $(
|
||||
message_actions.append_messages
|
||||
|
@ -940,7 +941,6 @@ export class MessageListView {
|
|||
$rendered_groups = this._render_group({
|
||||
message_groups: message_actions.append_groups,
|
||||
use_match_properties: this.list.is_keyword_search(),
|
||||
table_name: this.table_name,
|
||||
});
|
||||
|
||||
$dom_messages = $rendered_groups.find(".message_row");
|
||||
|
@ -962,7 +962,7 @@ export class MessageListView {
|
|||
// this next line seems to prevent the Chrome bug from firing.
|
||||
message_viewport.scrollTop();
|
||||
|
||||
$table.append($rendered_groups);
|
||||
this.$list.append($rendered_groups);
|
||||
condense.condense_and_collapse($dom_messages);
|
||||
}
|
||||
|
||||
|
@ -1436,7 +1436,7 @@ export class MessageListView {
|
|||
// We do not want to call .empty() because that also clears
|
||||
// jQuery data. This does mean, however, that we need to be
|
||||
// mindful of memory leaks.
|
||||
rows.get_table(this.table_name).children().detach();
|
||||
this.$list.children().detach();
|
||||
this._rows.clear();
|
||||
this._message_groups = [];
|
||||
this.message_containers.clear();
|
||||
|
@ -1455,7 +1455,7 @@ export class MessageListView {
|
|||
}
|
||||
|
||||
clear_trailing_bookend() {
|
||||
const $trailing_bookend = rows.get_table(this.table_name).find(".trailing_bookend");
|
||||
const $trailing_bookend = this.$list.find(".trailing_bookend");
|
||||
$trailing_bookend.remove();
|
||||
}
|
||||
|
||||
|
@ -1484,7 +1484,7 @@ export class MessageListView {
|
|||
is_web_public,
|
||||
}),
|
||||
);
|
||||
rows.get_table(this.table_name).append($rendered_trailing_bookend);
|
||||
this.$list.append($rendered_trailing_bookend);
|
||||
}
|
||||
|
||||
selected_row() {
|
||||
|
@ -1501,7 +1501,7 @@ export class MessageListView {
|
|||
this._rows.delete(old_id);
|
||||
|
||||
$row.attr("zid", new_id);
|
||||
$row.attr("id", this.table_name + new_id);
|
||||
$row.attr("id", `message-row-${this.list.id}-` + new_id);
|
||||
$row.removeClass("local");
|
||||
this._rows.set(new_id, $row);
|
||||
}
|
||||
|
@ -1570,8 +1570,7 @@ export class MessageListView {
|
|||
return 0;
|
||||
}
|
||||
|
||||
const $table = rows.get_table(this.table_name);
|
||||
const $headers = $table.find(".message_header");
|
||||
const $headers = this.$list.find(".message_header");
|
||||
const iterable_headers = $headers.toArray();
|
||||
let start = 0;
|
||||
let end = iterable_headers.length - 1;
|
||||
|
@ -1670,8 +1669,7 @@ export class MessageListView {
|
|||
}
|
||||
|
||||
update_recipient_bar_background_color() {
|
||||
const $table = rows.get_table(this.table_name);
|
||||
const $stream_headers = $table.find(".message_header_stream");
|
||||
const $stream_headers = this.$list.find(".message_header_stream");
|
||||
for (const stream_header of $stream_headers) {
|
||||
const $stream_header = $(stream_header);
|
||||
stream_color.update_stream_recipient_color($stream_header);
|
||||
|
@ -1689,8 +1687,7 @@ export class MessageListView {
|
|||
}
|
||||
|
||||
show_messages_as_unread(message_ids) {
|
||||
const $table = rows.get_table(this.table_name);
|
||||
const $rows_to_show_as_unread = $table.find(".message_row").filter((_index, $row) => {
|
||||
const $rows_to_show_as_unread = this.$list.find(".message_row").filter((_index, $row) => {
|
||||
const message_id = Number.parseFloat($row.getAttribute("zid"));
|
||||
return message_ids.includes(message_id);
|
||||
});
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import $ from "jquery";
|
||||
import assert from "minimalistic-assert";
|
||||
|
||||
import * as blueslip from "./blueslip";
|
||||
|
@ -15,11 +14,12 @@ type MessageListView = {
|
|||
_render_win_start: number;
|
||||
_render_win_end: number;
|
||||
sticky_recipient_message_id: number | undefined;
|
||||
$list: JQuery;
|
||||
};
|
||||
|
||||
export type RenderInfo = {need_user_to_scroll: boolean};
|
||||
export type MessageList = {
|
||||
table_name: string;
|
||||
id: number;
|
||||
view: MessageListView;
|
||||
selected_id: () => number;
|
||||
selected_row: () => JQuery;
|
||||
|
@ -61,7 +61,7 @@ export function all_rendered_message_lists(): MessageList[] {
|
|||
|
||||
export function all_current_message_rows(): JQuery {
|
||||
assert(current !== undefined);
|
||||
return $(`#${CSS.escape(current.table_name)}.message-list .message_row`);
|
||||
return current.view.$list.find(".message_row");
|
||||
}
|
||||
|
||||
export function update_recipient_bar_background_color(): void {
|
||||
|
|
|
@ -420,16 +420,19 @@ export function activate(raw_terms, opts) {
|
|||
|
||||
const msg_list = new message_list.MessageList({
|
||||
data: msg_data,
|
||||
table_name: "zfilt",
|
||||
});
|
||||
|
||||
// Show the new set of messages. It is important to set message_lists.current to
|
||||
// the view right as it's being shown, because we rely on message_lists.current
|
||||
// being shown for deciding when to condense messages.
|
||||
$("body").addClass("narrowed_view");
|
||||
$("#zfilt").addClass("focused-message-list");
|
||||
$("#zhome").removeClass("focused-message-list");
|
||||
msg_list.view.$list.addClass("focused-message-list");
|
||||
message_lists.home.view.$list.removeClass("focused-message-list");
|
||||
|
||||
// Remove old message list from DOM.
|
||||
if (message_lists.current !== message_lists.home) {
|
||||
message_lists.current?.view.$list.remove();
|
||||
}
|
||||
message_lists.set_current(msg_list);
|
||||
|
||||
let then_select_offset;
|
||||
|
@ -1003,7 +1006,7 @@ function handle_post_narrow_deactivate_processes(msg_list) {
|
|||
message_feed_top_notices.update_top_of_narrow_notices(msg_list);
|
||||
|
||||
// We may need to scroll to the selected message after swapping
|
||||
// the currently displayed center panel to zhome.
|
||||
// the currently displayed center panel to All messages.
|
||||
message_viewport.maybe_scroll_to_selected();
|
||||
}
|
||||
|
||||
|
@ -1076,11 +1079,14 @@ export function deactivate() {
|
|||
narrow_state.set_has_shown_message_list_view();
|
||||
|
||||
$("body").removeClass("narrowed_view");
|
||||
$("#zfilt").removeClass("focused-message-list");
|
||||
$("#zhome").addClass("focused-message-list");
|
||||
message_lists.home.view.$list.addClass("focused-message-list");
|
||||
// Remove old message list from DOM.
|
||||
if (message_lists.current !== message_lists.home) {
|
||||
message_lists.current?.view.$list.remove();
|
||||
}
|
||||
message_lists.set_current(message_lists.home);
|
||||
message_lists.current.resume_reading();
|
||||
condense.condense_and_collapse($("#zhome div.message_row"));
|
||||
condense.condense_and_collapse(message_lists.home.view.$list.find(".message_row"));
|
||||
|
||||
reset_ui_state();
|
||||
compose_recipient.handle_middle_pane_transition();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as message_lists from "./message_lists";
|
||||
import * as message_viewport from "./message_viewport";
|
||||
import * as rows from "./rows";
|
||||
import * as unread_ops from "./unread_ops";
|
||||
|
||||
function go_to_row(msg_id) {
|
||||
|
@ -23,9 +22,9 @@ export function down(with_centering) {
|
|||
if (with_centering) {
|
||||
// At the last message, scroll to the bottom so we have
|
||||
// lots of nice whitespace for new messages coming in.
|
||||
const $current_msg_table = rows.get_table(message_lists.current.table_name);
|
||||
const $current_msg_list = message_lists.current.view.$list;
|
||||
message_viewport.scrollTop(
|
||||
($current_msg_table.outerHeight(true) ?? 0) - message_viewport.height() * 0.1,
|
||||
($current_msg_list.outerHeight(true) ?? 0) - message_viewport.height() * 0.1,
|
||||
);
|
||||
unread_ops.process_scrolled_to_bottom();
|
||||
}
|
||||
|
|
|
@ -112,16 +112,6 @@ export function local_echo_id($message_row: JQuery): string | undefined {
|
|||
return zid;
|
||||
}
|
||||
|
||||
const valid_table_names = new Set(["zhome", "zfilt"]);
|
||||
|
||||
export function get_table(table_name: string): JQuery {
|
||||
if (!valid_table_names.has(table_name)) {
|
||||
return $();
|
||||
}
|
||||
|
||||
return $(`#${CSS.escape(table_name)}`);
|
||||
}
|
||||
|
||||
export function get_message_id(elem: string): number | undefined {
|
||||
// Gets the message_id for elem, where elem is a DOM
|
||||
// element inside a message. This is typically used
|
||||
|
|
|
@ -4,7 +4,6 @@ import * as inbox_util from "./inbox_util";
|
|||
import * as message_lists from "./message_lists";
|
||||
import * as message_view_header from "./message_view_header";
|
||||
import * as overlays from "./overlays";
|
||||
import * as rows from "./rows";
|
||||
import * as stream_color from "./stream_color";
|
||||
import * as stream_data from "./stream_data";
|
||||
|
||||
|
@ -30,8 +29,11 @@ function update_stream_privacy_color(id, color) {
|
|||
function update_message_recipient_color(stream_name, color) {
|
||||
const recipient_color = stream_color.get_recipient_bar_color(color);
|
||||
for (const msg_list of message_lists.all_rendered_message_lists()) {
|
||||
const $table = rows.get_table(msg_list.table_name);
|
||||
update_table_message_recipient_stream_color($table, stream_name, recipient_color);
|
||||
update_table_message_recipient_stream_color(
|
||||
msg_list.view.$list,
|
||||
stream_name,
|
||||
recipient_color,
|
||||
);
|
||||
}
|
||||
|
||||
// Update color for drafts if open.
|
||||
|
|
|
@ -404,8 +404,8 @@ export function update_timestamps(): void {
|
|||
const className = entry.className;
|
||||
const $elements = $(`.${CSS.escape(className)}`);
|
||||
// The element might not exist any more (because it
|
||||
// was in the zfilt table, or because we added
|
||||
// messages above it and re-collapsed).
|
||||
// was in the narrowed message list which was removed,
|
||||
// or because we added messages above it and re-collapsed).
|
||||
if ($elements.length > 0) {
|
||||
const time = entry.time;
|
||||
const rendered_time = render_now(time, today);
|
||||
|
|
|
@ -118,7 +118,7 @@ export function get_item(key, config, file_id) {
|
|||
return "message-edit-file-input";
|
||||
case "drag_drop_container":
|
||||
return $(
|
||||
`#${message_lists.current.table_name}${CSS.escape(
|
||||
`#message-row-${message_lists.current.id}-${CSS.escape(
|
||||
config.row,
|
||||
)} .message_edit_form`,
|
||||
);
|
||||
|
|
|
@ -49,7 +49,10 @@ export function activate(in_opts) {
|
|||
});
|
||||
};
|
||||
|
||||
if ($row.attr("id").startsWith("zhome") && narrow_state.active()) {
|
||||
if (
|
||||
$row.attr("id").startsWith(`message-row-${message_lists.home.id}-`) &&
|
||||
narrow_state.active()
|
||||
) {
|
||||
// Don't place widget in a home message row if we are narrowed
|
||||
// to active state
|
||||
return;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
{{> recipient_row use_match_properties=../use_match_properties}}
|
||||
{{#each message_containers}}
|
||||
{{#with this}}
|
||||
{{> single_message use_match_properties=../../use_match_properties table_name=../../table_name}}
|
||||
{{> single_message use_match_properties=../../use_match_properties message_list_id=../../message_list_id}}
|
||||
{{/with}}
|
||||
{{/each}}
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<div class="message-list" data-message-list-id="{{ message_list_id }}" role="list" aria-live="polite" aria-label="{{t 'Messages' }}"></div>
|
|
@ -1,4 +1,4 @@
|
|||
<div zid="{{msg/id}}" id="{{table_name}}{{msg/id}}"
|
||||
<div zid="{{msg/id}}" id="message-row-{{message_list_id}}-{{msg/id}}"
|
||||
class="message_row{{#unless msg/is_stream}} private-message{{/unless}}{{#include_sender}} include-sender{{/include_sender}}{{#if mention_classname}} {{mention_classname}}{{/if}}{{#msg.unread}} unread{{/msg.unread}} {{#if msg.locally_echoed}}locally-echoed{{/if}} selectable_row"
|
||||
role="listitem">
|
||||
{{#if want_date_divider}}
|
||||
|
|
|
@ -65,11 +65,9 @@ const alice = {
|
|||
people.add_active_user(alice);
|
||||
|
||||
function make_home_msg_list() {
|
||||
const table_name = "whatever";
|
||||
const filter = new Filter([]);
|
||||
|
||||
const list = new message_list.MessageList({
|
||||
table_name,
|
||||
filter,
|
||||
});
|
||||
return list;
|
||||
|
@ -297,7 +295,6 @@ function simulate_narrow() {
|
|||
const filter = new Filter([{operator: "dm", operand: alice.email}]);
|
||||
|
||||
const msg_list = new message_list.MessageList({
|
||||
table_name: "zfilt",
|
||||
filter,
|
||||
});
|
||||
message_lists.current = msg_list;
|
||||
|
|
|
@ -20,18 +20,6 @@ mock_esm("../src/timerender", {
|
|||
},
|
||||
});
|
||||
|
||||
mock_esm("../src/rows", {
|
||||
get_table() {
|
||||
return {
|
||||
children() {
|
||||
return {
|
||||
detach: noop,
|
||||
};
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
mock_esm("../src/people", {
|
||||
sender_is_bot: () => false,
|
||||
sender_is_guest: () => false,
|
||||
|
@ -47,9 +35,10 @@ const muted_users = zrequire("muted_users");
|
|||
let next_timestamp = 1500000000;
|
||||
|
||||
function test(label, f) {
|
||||
run_test(label, ({override}) => {
|
||||
run_test(label, ({override, mock_template}) => {
|
||||
muted_users.set_muted_users([]);
|
||||
f({override});
|
||||
mock_template("message_list.hbs", false, noop);
|
||||
f({override, mock_template});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -80,7 +69,13 @@ test("msg_moved_var", () => {
|
|||
}
|
||||
|
||||
function build_list(message_groups) {
|
||||
const list = new MessageListView(undefined, undefined, true);
|
||||
const list = new MessageListView(
|
||||
{
|
||||
id: 1,
|
||||
},
|
||||
true,
|
||||
true,
|
||||
);
|
||||
list._message_groups = message_groups;
|
||||
return list;
|
||||
}
|
||||
|
@ -229,7 +224,13 @@ test("msg_edited_vars", () => {
|
|||
}
|
||||
|
||||
function build_list(message_groups) {
|
||||
const list = new MessageListView(undefined, undefined, true);
|
||||
const list = new MessageListView(
|
||||
{
|
||||
id: 1,
|
||||
},
|
||||
true,
|
||||
true,
|
||||
);
|
||||
list._message_groups = message_groups;
|
||||
return list;
|
||||
}
|
||||
|
@ -293,7 +294,13 @@ test("muted_message_vars", () => {
|
|||
}
|
||||
|
||||
function build_list(message_groups) {
|
||||
const list = new MessageListView(undefined, undefined, true);
|
||||
const list = new MessageListView(
|
||||
{
|
||||
id: 1,
|
||||
},
|
||||
true,
|
||||
true,
|
||||
);
|
||||
list._message_groups = message_groups;
|
||||
return list;
|
||||
}
|
||||
|
@ -403,7 +410,8 @@ test("muted_message_vars", () => {
|
|||
})();
|
||||
});
|
||||
|
||||
test("merge_message_groups", () => {
|
||||
test("merge_message_groups", ({mock_template}) => {
|
||||
mock_template("message_list.hbs", false, noop);
|
||||
// MessageListView has lots of DOM code, so we are going to test the message
|
||||
// group merging logic on its own.
|
||||
|
||||
|
@ -433,15 +441,14 @@ test("merge_message_groups", () => {
|
|||
}
|
||||
|
||||
function build_list(message_groups) {
|
||||
const table_name = "zfilt";
|
||||
const filter = new Filter([{operator: "stream", operand: "foo"}]);
|
||||
|
||||
const list = new message_list.MessageList({
|
||||
table_name,
|
||||
filter,
|
||||
is_node_test: true,
|
||||
});
|
||||
|
||||
const view = new MessageListView(list, table_name, true);
|
||||
const view = new MessageListView(list, true, true);
|
||||
view._message_groups = message_groups;
|
||||
view.list.unsubscribed_bookend_content = noop;
|
||||
view.list.subscribed_bookend_content = noop;
|
||||
|
@ -687,19 +694,19 @@ test("merge_message_groups", () => {
|
|||
})();
|
||||
});
|
||||
|
||||
test("render_windows", () => {
|
||||
test("render_windows", ({mock_template}) => {
|
||||
mock_template("message_list.hbs", false, noop);
|
||||
// We only render up to 400 messages at a time in our message list,
|
||||
// and we only change the window (which is a range, really, with
|
||||
// start/end) when the pointer moves outside of the window or close
|
||||
// to the edges.
|
||||
|
||||
const view = (function make_view() {
|
||||
const table_name = "zfilt";
|
||||
const filter = new Filter([]);
|
||||
|
||||
const list = new message_list.MessageList({
|
||||
table_name,
|
||||
filter,
|
||||
is_node_test: true,
|
||||
});
|
||||
|
||||
const view = list.view;
|
||||
|
@ -731,6 +738,7 @@ test("render_windows", () => {
|
|||
id: i,
|
||||
}));
|
||||
list.selected_idx = () => 0;
|
||||
list.view.clear_table = noop;
|
||||
list.clear();
|
||||
|
||||
list.add_messages(messages, {});
|
||||
|
|
|
@ -21,8 +21,23 @@ const compose_recipient = mock_esm("../src/compose_recipient");
|
|||
const message_fetch = mock_esm("../src/message_fetch");
|
||||
const message_list = mock_esm("../src/message_list");
|
||||
const message_lists = mock_esm("../src/message_lists", {
|
||||
home: {},
|
||||
current: {},
|
||||
home: {
|
||||
view: {
|
||||
$list: {
|
||||
removeClass: noop,
|
||||
addClass: noop,
|
||||
},
|
||||
},
|
||||
},
|
||||
current: {
|
||||
view: {
|
||||
$list: {
|
||||
remove: noop,
|
||||
removeClass: noop,
|
||||
addClass: noop,
|
||||
},
|
||||
},
|
||||
},
|
||||
set_current(msg_list) {
|
||||
message_lists.current = msg_list;
|
||||
},
|
||||
|
@ -117,6 +132,12 @@ function stub_message_list() {
|
|||
set_message_offset(offset) {
|
||||
this.offset = offset;
|
||||
},
|
||||
|
||||
$list: {
|
||||
remove: noop,
|
||||
removeClass: noop,
|
||||
addClass: noop,
|
||||
},
|
||||
};
|
||||
|
||||
get(msg_id) {
|
||||
|
|
|
@ -30,7 +30,7 @@ const compose_ui = zrequire("compose_ui");
|
|||
const upload = zrequire("upload");
|
||||
const message_lists = zrequire("message_lists");
|
||||
message_lists.current = {
|
||||
table_name: "zfilt",
|
||||
id: "1",
|
||||
};
|
||||
function test(label, f) {
|
||||
run_test(label, (helpers) => {
|
||||
|
@ -129,7 +129,7 @@ test("get_item", () => {
|
|||
assert.equal(upload.get_item("source", {mode: "edit", row: 123}), "message-edit-file-input");
|
||||
assert.equal(
|
||||
upload.get_item("drag_drop_container", {mode: "edit", row: 1}),
|
||||
$(`#zfilt${CSS.escape(1)} .message_edit_form`),
|
||||
$(`#message-row-1-${CSS.escape(1)} .message_edit_form`),
|
||||
);
|
||||
assert.equal(
|
||||
upload.get_item("markdown_preview_hide_button", {mode: "edit", row: 65}),
|
||||
|
@ -769,7 +769,7 @@ test("main_file_drop_edit_mode", ({override, override_rewire}) => {
|
|||
prevent_default_counter += 1;
|
||||
},
|
||||
};
|
||||
const $drag_drop_container = $(`#zfilt${CSS.escape(40)} .message_edit_form`);
|
||||
const $drag_drop_container = $(`#message-row-1-${CSS.escape(40)} .message_edit_form`);
|
||||
|
||||
// Dragover event test
|
||||
const dragover_handler = $(".app, #navbar-fixed-container").get_on_handler("dragover");
|
||||
|
|
|
@ -54,7 +54,7 @@ const fake_poll_widget = {
|
|||
},
|
||||
};
|
||||
|
||||
const message_lists = mock_esm("../src/message_lists", {current: {}});
|
||||
const message_lists = mock_esm("../src/message_lists", {current: {}, home: {id: 1}});
|
||||
const narrow_state = mock_esm("../src/narrow_state");
|
||||
mock_esm("../src/poll_widget", fake_poll_widget);
|
||||
|
||||
|
@ -80,8 +80,8 @@ test("activate", ({override}) => {
|
|||
// Both widgetize.activate and widgetize.handle_event are tested
|
||||
// here to use the "caching" of widgets
|
||||
const $row = $.create("<stub message row>");
|
||||
$row.attr("id", "zhome2909");
|
||||
const $message_content = $.create("#zhome2909");
|
||||
$row.attr("id", "message-row-1-2909");
|
||||
const $message_content = $.create("#message-row-1-2909");
|
||||
$row.set_find_results(".message_content", $message_content);
|
||||
|
||||
let narrow_active;
|
||||
|
|
Loading…
Reference in New Issue