mirror of
https://github.com/zulip/zulip.git
synced 2025-11-08 07:52:19 +00:00
This commit introduces the change of rendering private messages section as collapsible, whose data-fetching logic came with zulip#21357. We now have separated out `Private messages` from `top_left_corner` section and shifted it below the `global_filters` in a different separate section along with stream list with common scroll bar in left-sidebar. The new PM section will be opened by-default on loading the page and will have a toggle-icon in its header, clicking on which makes the section collapse/expand accordingly. In default view, only recent 5 PM threads would be shown and would append the active conversation as the 6th one at last if not present in those 5, similar to how topics list work. In PM section with unreads, a maximum of 8 conversations would be shown and rest of them would be hidden behind the 'more conversations' li-item, clicking on which takes to the zoomedIn view of PM section where all the present PM threads would be visible and rest of the sections of left-sidebar will get collapsed. Fixes #20870. Co-authored-by: Aman Agrawal <amanagr@zulip.com>
256 lines
5.8 KiB
JavaScript
256 lines
5.8 KiB
JavaScript
"use strict";
|
|
|
|
const {strict: assert} = require("assert");
|
|
|
|
const {zrequire} = require("../zjsunit/namespace");
|
|
const {run_test} = require("../zjsunit/test");
|
|
const blueslip = require("../zjsunit/zblueslip");
|
|
|
|
const vdom = zrequire("vdom");
|
|
|
|
run_test("basics", () => {
|
|
const opts = {
|
|
keyed_nodes: [],
|
|
attrs: [
|
|
["class", "foo"],
|
|
["title", 'cats & <"dogs">'],
|
|
],
|
|
};
|
|
|
|
const ul = vdom.ul(opts);
|
|
|
|
const html = vdom.render_tag(ul);
|
|
|
|
assert.equal(html, '<ul class="foo" title="cats & <"dogs">">\n\n</ul>');
|
|
});
|
|
|
|
run_test("attribute escaping", () => {
|
|
// So far most of the time our attributes are
|
|
// hard-coded classes like "pm-list",
|
|
// but we need to be defensive about future code
|
|
// that might use data from possibly malicious users.
|
|
const opts = {
|
|
keyed_nodes: [],
|
|
attrs: [
|
|
["class", '">something evil<div class="'],
|
|
["title", "apples & oranges"],
|
|
],
|
|
};
|
|
|
|
const ul = vdom.ul(opts);
|
|
|
|
const html = vdom.render_tag(ul);
|
|
|
|
assert.equal(
|
|
html,
|
|
'<ul class="">something evil<div class="" ' +
|
|
'title="apples & oranges">\n\n</ul>',
|
|
);
|
|
});
|
|
|
|
run_test("attribute updates", () => {
|
|
const opts = {
|
|
keyed_nodes: [],
|
|
attrs: [
|
|
["class", "same"],
|
|
["color", "blue"],
|
|
["id", "101"],
|
|
],
|
|
};
|
|
|
|
const ul = vdom.ul(opts);
|
|
|
|
const html = vdom.render_tag(ul);
|
|
|
|
assert.equal(html, '<ul class="same" color="blue" id="101">\n\n</ul>');
|
|
|
|
let updated;
|
|
let removed;
|
|
|
|
function find() {
|
|
return {
|
|
children: () => [],
|
|
|
|
attr: (k, v) => {
|
|
assert.equal(k, "color");
|
|
assert.equal(v, "red");
|
|
updated = true;
|
|
},
|
|
|
|
removeAttr: (k) => {
|
|
assert.equal(k, "id");
|
|
removed = true;
|
|
},
|
|
};
|
|
}
|
|
|
|
const new_opts = {
|
|
keyed_nodes: [],
|
|
attrs: [
|
|
["class", "same"], // unchanged
|
|
["color", "red"],
|
|
],
|
|
};
|
|
|
|
const new_ul = vdom.ul(new_opts);
|
|
const replace_content = undefined;
|
|
|
|
vdom.update(replace_content, find, new_ul, ul);
|
|
|
|
assert.ok(updated);
|
|
assert.ok(removed);
|
|
});
|
|
|
|
function make_child(i, name) {
|
|
const render = () => "<li>" + name + "</li>";
|
|
|
|
const eq = (other) => name === other.name;
|
|
|
|
return {
|
|
key: i,
|
|
render,
|
|
name,
|
|
eq,
|
|
};
|
|
}
|
|
|
|
function make_children(lst) {
|
|
return lst.map((i) => make_child(i, "foo" + i));
|
|
}
|
|
|
|
run_test("children", () => {
|
|
let rendered_html;
|
|
|
|
function replace_content(html) {
|
|
rendered_html = html;
|
|
}
|
|
|
|
const find = undefined;
|
|
|
|
const nodes = make_children([1, 2, 3]);
|
|
|
|
const opts = {
|
|
keyed_nodes: nodes,
|
|
attrs: [],
|
|
};
|
|
|
|
const ul = vdom.ul(opts);
|
|
|
|
vdom.update(replace_content, find, ul);
|
|
|
|
assert.equal(rendered_html, "<ul>\n<li>foo1</li>\n<li>foo2</li>\n<li>foo3</li>\n</ul>");
|
|
|
|
// Force a complete redraw.
|
|
const new_nodes = make_children([4, 5]);
|
|
const new_opts = {
|
|
keyed_nodes: new_nodes,
|
|
attrs: [["class", "main"]],
|
|
};
|
|
|
|
const new_ul = vdom.ul(new_opts);
|
|
vdom.update(replace_content, find, new_ul, ul);
|
|
|
|
assert.equal(rendered_html, '<ul class="main">\n<li>foo4</li>\n<li>foo5</li>\n</ul>');
|
|
});
|
|
|
|
run_test("partial updates", () => {
|
|
let rendered_html;
|
|
|
|
let replace_content = (html) => {
|
|
rendered_html = html;
|
|
};
|
|
|
|
let find;
|
|
|
|
const nodes = make_children([1, 2, 3]);
|
|
|
|
const opts = {
|
|
keyed_nodes: nodes,
|
|
attrs: [],
|
|
};
|
|
|
|
const ul = vdom.ul(opts);
|
|
|
|
vdom.update(replace_content, find, ul);
|
|
|
|
assert.equal(rendered_html, "<ul>\n<li>foo1</li>\n<li>foo2</li>\n<li>foo3</li>\n</ul>");
|
|
|
|
/* istanbul ignore next */
|
|
replace_content = () => {
|
|
throw new Error("should not replace entire html");
|
|
};
|
|
|
|
let patched_html;
|
|
|
|
find = () => ({
|
|
children: () => ({
|
|
eq: (i) => {
|
|
assert.equal(i, 0);
|
|
return {
|
|
replaceWith: (html) => {
|
|
patched_html = html;
|
|
},
|
|
};
|
|
},
|
|
}),
|
|
});
|
|
|
|
const new_nodes = make_children([1, 2, 3]);
|
|
new_nodes[0] = make_child(1, "modified1");
|
|
|
|
const new_opts = {
|
|
keyed_nodes: new_nodes,
|
|
attrs: [],
|
|
};
|
|
|
|
const new_ul = vdom.ul(new_opts);
|
|
vdom.update(replace_content, find, new_ul, ul);
|
|
|
|
assert.equal(patched_html, "<li>modified1</li>");
|
|
});
|
|
|
|
run_test("eq_array easy cases", () => {
|
|
/* istanbul ignore next */
|
|
const bogus_eq = () => {
|
|
throw new Error("we should not be comparing elements");
|
|
};
|
|
|
|
assert.equal(vdom.eq_array(undefined, undefined, bogus_eq), true);
|
|
|
|
const x = [1, 2, 3];
|
|
assert.equal(vdom.eq_array(x, undefined, bogus_eq), false);
|
|
|
|
assert.equal(vdom.eq_array(undefined, x, bogus_eq), false);
|
|
|
|
assert.equal(vdom.eq_array(x, x, bogus_eq), true);
|
|
|
|
// length check should also short-circuit
|
|
const y = [1, 2, 3, 4, 5];
|
|
assert.equal(vdom.eq_array(x, y, bogus_eq), false);
|
|
|
|
// same length, same values, but different order
|
|
const eq = (a, b) => a === b;
|
|
const z = [3, 2, 1];
|
|
assert.equal(vdom.eq_array(x, z, eq), false);
|
|
});
|
|
|
|
run_test("eq_array element-wise", () => {
|
|
const a = [51, 32, 93];
|
|
const b = [31, 52, 43];
|
|
const eq = (a, b) => a % 10 === b % 10;
|
|
assert.equal(vdom.eq_array(a, b, eq), true);
|
|
});
|
|
|
|
run_test("error checking", () => {
|
|
blueslip.expect("error", "We need keyed_nodes for updates.");
|
|
|
|
const replace_content = "whatever";
|
|
const find = "whatever";
|
|
const ul = {opts: {attrs: []}};
|
|
|
|
vdom.update(replace_content, find, ul, ul);
|
|
|
|
blueslip.expect("error", "We need keyed_nodes to render innards.");
|
|
vdom.render_tag(ul);
|
|
});
|