mirror of https://github.com/zulip/zulip.git
stream_list: Sort muted to end of sections and add labels.
The stream list left sidebar currently has 3 sections: * Pinned (+ Muted pinned streams) * Active (+ Muted active streams) * Inactive streams Previously, these sections were separated by horizontal lines, which did not provide an easy way to discern why there were sections. We add labels to these section dividers to help with this. Additionally, within each section, we now sort all muted streams to the bottom, so that they general minimal clutter. Fixes #19812.
This commit is contained in:
parent
0a278c39d2
commit
c1b5021d84
|
@ -318,6 +318,12 @@ test("is_active", () => {
|
|||
assert.ok(stream_data.is_active(sub));
|
||||
});
|
||||
|
||||
test("is_muted_active", () => {
|
||||
const sub = {name: "cats", subscribed: true, stream_id: 111, is_muted: true};
|
||||
stream_data.add_sub(sub);
|
||||
assert.ok(stream_data.is_muted_active(sub));
|
||||
});
|
||||
|
||||
test("admin_options", () => {
|
||||
function make_sub() {
|
||||
const sub = {
|
||||
|
|
|
@ -124,6 +124,7 @@ test("update_property", ({override}) => {
|
|||
{
|
||||
const stub = make_stub();
|
||||
override(stream_muting, "update_is_muted", stub.f);
|
||||
override(stream_list, "refresh_muted_or_unmuted_stream", noop);
|
||||
stream_events.update_property(stream_id, "in_home_view", false);
|
||||
assert.equal(stub.num_calls, 1);
|
||||
const args = stub.get_args("sub", "val");
|
||||
|
|
|
@ -12,10 +12,11 @@ set_global("document", "document-stub");
|
|||
page_params.is_admin = false;
|
||||
page_params.realm_users = [];
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
// We use this with override.
|
||||
let num_unread_for_stream;
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
const narrow_state = mock_esm("../../static/js/narrow_state");
|
||||
const topic_list = mock_esm("../../static/js/topic_list");
|
||||
mock_esm("../../static/js/keydown_util", {
|
||||
|
@ -49,6 +50,11 @@ const social = {
|
|||
subscribed: true,
|
||||
};
|
||||
|
||||
// flag to check if subheader is rendered
|
||||
let pinned_subheader_flag = false;
|
||||
let active_subheader_flag = false;
|
||||
let inactive_subheader_flag = false;
|
||||
|
||||
function create_devel_sidebar_row({mock_template}) {
|
||||
const $devel_count = $.create("devel-count");
|
||||
const $subscription_block = $.create("devel-block");
|
||||
|
@ -87,6 +93,22 @@ function create_social_sidebar_row({mock_template}) {
|
|||
assert.equal($social_count.text(), "99");
|
||||
}
|
||||
|
||||
function create_stream_subheader({mock_template}) {
|
||||
mock_template("streams_subheader.hbs", false, (data) => {
|
||||
if (data.subheader_name === "translated: Pinned") {
|
||||
pinned_subheader_flag = true;
|
||||
return "<pinned-subheader-stub>";
|
||||
} else if (data.subheader_name === "translated: Active") {
|
||||
active_subheader_flag = true;
|
||||
return "<active-subheader-stub>";
|
||||
}
|
||||
|
||||
assert.ok(data.subheader_name === "translated: Inactive");
|
||||
inactive_subheader_flag = true;
|
||||
return "<inactive-subheader-stub>";
|
||||
});
|
||||
}
|
||||
|
||||
function test_ui(label, f) {
|
||||
run_test(label, (helpers) => {
|
||||
stream_data.clear_subscriptions();
|
||||
|
@ -105,8 +127,10 @@ test_ui("create_sidebar_row", ({override_rewire, mock_template}) => {
|
|||
|
||||
create_devel_sidebar_row({mock_template});
|
||||
create_social_sidebar_row({mock_template});
|
||||
create_stream_subheader({mock_template});
|
||||
|
||||
const split = '<hr class="stream-split">';
|
||||
const $pinned_subheader = $("<pinned-subheader-stub>");
|
||||
const $active_subheader = $("<active-subheader-stub>");
|
||||
const $devel_sidebar = $("<devel-sidebar-row-stub>");
|
||||
const $social_sidebar = $("<social-sidebar-row-stub>");
|
||||
|
||||
|
@ -123,14 +147,16 @@ test_ui("create_sidebar_row", ({override_rewire, mock_template}) => {
|
|||
stream_list.build_stream_list();
|
||||
|
||||
assert.ok(topic_list_cleared);
|
||||
|
||||
const expected_elems = [
|
||||
$pinned_subheader.html(), // separator
|
||||
$devel_sidebar, // pinned
|
||||
split, // separator
|
||||
$active_subheader.html(), // separator
|
||||
$social_sidebar, // not pinned
|
||||
];
|
||||
|
||||
assert.deepEqual(appended_elems, expected_elems);
|
||||
assert.ok(pinned_subheader_flag);
|
||||
assert.ok(active_subheader_flag);
|
||||
|
||||
const $social_li = $("<social-sidebar-row-stub>");
|
||||
const stream_id = social.stream_id;
|
||||
|
@ -181,6 +207,7 @@ test_ui("pinned_streams_never_inactive", ({override_rewire, mock_template}) => {
|
|||
|
||||
create_devel_sidebar_row({mock_template});
|
||||
create_social_sidebar_row({mock_template});
|
||||
create_stream_subheader({mock_template});
|
||||
|
||||
// non-pinned streams can be made inactive
|
||||
const $social_sidebar = $("<social-sidebar-row-stub>");
|
||||
|
@ -306,12 +333,12 @@ test_ui("zoom_in_and_zoom_out", () => {
|
|||
children: [elem($label1), elem($label2)],
|
||||
});
|
||||
|
||||
const $splitter = $.create("hr stub");
|
||||
const $splitter = $.create("<active-subheader-stub>");
|
||||
|
||||
$splitter.show();
|
||||
assert.ok($splitter.visible());
|
||||
|
||||
$.create(".stream-split", {
|
||||
$.create(".streams_subheader", {
|
||||
children: [elem($splitter)],
|
||||
});
|
||||
|
||||
|
@ -363,7 +390,8 @@ test_ui("zoom_in_and_zoom_out", () => {
|
|||
assert.ok($("#streams_list").hasClass("zoom-out"));
|
||||
});
|
||||
|
||||
test_ui("narrowing", () => {
|
||||
test_ui("narrowing", ({mock_template}) => {
|
||||
create_stream_subheader({mock_template});
|
||||
initialize_stream_data();
|
||||
|
||||
topic_list.close = noop;
|
||||
|
@ -429,7 +457,13 @@ test_ui("focus_user_filter", () => {
|
|||
click_handler(e);
|
||||
});
|
||||
|
||||
test_ui("sort_streams", ({override_rewire}) => {
|
||||
test_ui("sort_streams", ({override_rewire, mock_template}) => {
|
||||
create_stream_subheader({mock_template});
|
||||
// Set subheader flag to false
|
||||
pinned_subheader_flag = false;
|
||||
active_subheader_flag = false;
|
||||
inactive_subheader_flag = false;
|
||||
|
||||
// Get coverage on early-exit.
|
||||
stream_list.build_stream_list();
|
||||
|
||||
|
@ -444,19 +478,25 @@ test_ui("sort_streams", ({override_rewire}) => {
|
|||
|
||||
stream_list.build_stream_list();
|
||||
|
||||
const split = '<hr class="stream-split">';
|
||||
const $pinned_subheader = $("<pinned-subheader-stub>");
|
||||
const $active_subheader = $("<active-subheader-stub>");
|
||||
const $inactive_subheader = $("<inactive-subheader-stub>");
|
||||
const expected_elems = [
|
||||
$pinned_subheader.html(),
|
||||
$("<devel-sidebar-row-stub>"),
|
||||
$("<Rome-sidebar-row-stub>"),
|
||||
$("<test-sidebar-row-stub>"),
|
||||
split,
|
||||
$active_subheader.html(),
|
||||
$("<announce-sidebar-row-stub>"),
|
||||
$("<Denmark-sidebar-row-stub>"),
|
||||
split,
|
||||
$inactive_subheader.html(),
|
||||
$("<cars-sidebar-row-stub>"),
|
||||
];
|
||||
|
||||
assert.deepEqual(appended_elems, expected_elems);
|
||||
assert.ok(pinned_subheader_flag);
|
||||
assert.ok(active_subheader_flag);
|
||||
assert.ok(inactive_subheader_flag);
|
||||
|
||||
const streams = stream_sort.get_streams();
|
||||
|
||||
|
@ -479,9 +519,13 @@ test_ui("sort_streams", ({override_rewire}) => {
|
|||
assert.ok(!stream_list.stream_sidebar.has_row_for(stream_id));
|
||||
});
|
||||
|
||||
test_ui("separators_only_pinned_and_dormant", ({override_rewire}) => {
|
||||
test_ui("separators_only_pinned_and_dormant", ({override_rewire, mock_template}) => {
|
||||
// Test only pinned and dormant streams
|
||||
|
||||
create_stream_subheader({mock_template});
|
||||
pinned_subheader_flag = false;
|
||||
inactive_subheader_flag = false;
|
||||
|
||||
// Get coverage on early-exit.
|
||||
stream_list.build_stream_list();
|
||||
|
||||
|
@ -522,22 +566,27 @@ test_ui("separators_only_pinned_and_dormant", ({override_rewire}) => {
|
|||
|
||||
stream_list.build_stream_list();
|
||||
|
||||
const split = '<hr class="stream-split">';
|
||||
const $pinned_subheader = $("<pinned-subheader-stub>");
|
||||
const $inactive_subheader = $("<inactive-subheader-stub>");
|
||||
const expected_elems = [
|
||||
// pinned
|
||||
$pinned_subheader.html(), // pinned
|
||||
$("<devel-sidebar-row-stub>"),
|
||||
$("<Rome-sidebar-row-stub>"),
|
||||
split,
|
||||
// dormant
|
||||
$inactive_subheader.html(), // dormant
|
||||
$("<Denmark-sidebar-row-stub>"),
|
||||
];
|
||||
|
||||
assert.deepEqual(appended_elems, expected_elems);
|
||||
assert.ok(pinned_subheader_flag);
|
||||
assert.ok(inactive_subheader_flag);
|
||||
});
|
||||
|
||||
test_ui("separators_only_pinned", () => {
|
||||
test_ui("separators_only_pinned", ({mock_template}) => {
|
||||
// Test only pinned streams
|
||||
|
||||
create_stream_subheader({mock_template});
|
||||
pinned_subheader_flag = false;
|
||||
|
||||
// Get coverage on early-exit.
|
||||
stream_list.build_stream_list();
|
||||
|
||||
|
@ -566,20 +615,22 @@ test_ui("separators_only_pinned", () => {
|
|||
};
|
||||
|
||||
stream_list.build_stream_list();
|
||||
|
||||
const $pinned_subheader = $("<pinned-subheader-stub>");
|
||||
const expected_elems = [
|
||||
// pinned
|
||||
$pinned_subheader.html(), // pinned
|
||||
$("<devel-sidebar-row-stub>"),
|
||||
$("<Rome-sidebar-row-stub>"),
|
||||
// no separator at the end as no stream follows
|
||||
];
|
||||
|
||||
assert.deepEqual(appended_elems, expected_elems);
|
||||
assert.ok(pinned_subheader_flag);
|
||||
});
|
||||
|
||||
narrow_state.active = () => false;
|
||||
|
||||
test_ui("rename_stream", ({mock_template}) => {
|
||||
create_stream_subheader({mock_template});
|
||||
initialize_stream_data();
|
||||
|
||||
const sub = stream_data.get_sub_by_name("devel");
|
||||
|
|
|
@ -44,6 +44,20 @@ const stream_hyphen_underscore_slash = {
|
|||
stream_id: 6,
|
||||
pin_to_top: false,
|
||||
};
|
||||
const muted_active = {
|
||||
subscribed: true,
|
||||
name: "muted active",
|
||||
stream_id: 7,
|
||||
pin_to_top: false,
|
||||
is_muted: true,
|
||||
};
|
||||
const muted_pinned = {
|
||||
subscribed: true,
|
||||
name: "muted pinned",
|
||||
stream_id: 8,
|
||||
pin_to_top: true,
|
||||
is_muted: true,
|
||||
};
|
||||
|
||||
function sort_groups(query) {
|
||||
const streams = stream_data.subscribed_stream_ids();
|
||||
|
@ -61,6 +75,8 @@ test("no_subscribed_streams", () => {
|
|||
const sorted = sort_groups("");
|
||||
assert.deepEqual(sorted, {
|
||||
dormant_streams: [],
|
||||
muted_active_streams: [],
|
||||
muted_pinned_streams: [],
|
||||
normal_streams: [],
|
||||
pinned_streams: [],
|
||||
same_as_before: sorted.same_as_before,
|
||||
|
@ -75,6 +91,8 @@ test("basics", ({override_rewire}) => {
|
|||
stream_data.add_sub(clarinet);
|
||||
stream_data.add_sub(weaving);
|
||||
stream_data.add_sub(stream_hyphen_underscore_slash);
|
||||
stream_data.add_sub(muted_active);
|
||||
stream_data.add_sub(muted_pinned);
|
||||
|
||||
override_rewire(stream_data, "is_active", (sub) => sub.name !== "pneumonia");
|
||||
|
||||
|
@ -86,13 +104,16 @@ test("basics", ({override_rewire}) => {
|
|||
fast_tortoise.stream_id,
|
||||
stream_hyphen_underscore_slash.stream_id,
|
||||
]);
|
||||
assert.deepEqual(sorted.muted_pinned_streams, [muted_pinned.stream_id]);
|
||||
assert.deepEqual(sorted.muted_active_streams, [muted_active.stream_id]);
|
||||
assert.deepEqual(sorted.dormant_streams, [pneumonia.stream_id]);
|
||||
|
||||
// Test cursor helpers.
|
||||
assert.equal(stream_sort.first_stream_id(), scalene.stream_id);
|
||||
|
||||
assert.equal(stream_sort.prev_stream_id(scalene.stream_id), undefined);
|
||||
assert.equal(stream_sort.prev_stream_id(clarinet.stream_id), scalene.stream_id);
|
||||
assert.equal(stream_sort.prev_stream_id(muted_pinned.stream_id), scalene.stream_id);
|
||||
assert.equal(stream_sort.prev_stream_id(clarinet.stream_id), muted_pinned.stream_id);
|
||||
|
||||
assert.equal(
|
||||
stream_sort.next_stream_id(fast_tortoise.stream_id),
|
||||
|
@ -100,8 +121,13 @@ test("basics", ({override_rewire}) => {
|
|||
);
|
||||
assert.equal(
|
||||
stream_sort.next_stream_id(stream_hyphen_underscore_slash.stream_id),
|
||||
pneumonia.stream_id,
|
||||
muted_active.stream_id,
|
||||
);
|
||||
assert.equal(
|
||||
stream_sort.next_stream_id(fast_tortoise.stream_id),
|
||||
stream_hyphen_underscore_slash.stream_id,
|
||||
);
|
||||
assert.equal(stream_sort.next_stream_id(muted_active.stream_id), pneumonia.stream_id);
|
||||
assert.equal(stream_sort.next_stream_id(pneumonia.stream_id), undefined);
|
||||
|
||||
// Test filtering
|
||||
|
|
|
@ -204,6 +204,10 @@ export function is_active(sub) {
|
|||
return stream_topic_history.stream_has_topics(sub.stream_id) || sub.newly_subscribed;
|
||||
}
|
||||
|
||||
export function is_muted_active(sub) {
|
||||
return sub.is_muted && is_active(sub);
|
||||
}
|
||||
|
||||
export function rename_sub(sub, new_name) {
|
||||
const old_name = sub.name;
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ export function update_property(stream_id, property, value, other_values) {
|
|||
break;
|
||||
case "in_home_view":
|
||||
stream_muting.update_is_muted(sub, !value);
|
||||
stream_list.refresh_muted_or_unmuted_stream(sub);
|
||||
recent_topics_ui.complete_rerender();
|
||||
break;
|
||||
case "desktop_notifications":
|
||||
|
|
|
@ -3,10 +3,12 @@ import _ from "lodash";
|
|||
|
||||
import render_stream_privacy from "../templates/stream_privacy.hbs";
|
||||
import render_stream_sidebar_row from "../templates/stream_sidebar_row.hbs";
|
||||
import render_stream_subheader from "../templates/streams_subheader.hbs";
|
||||
|
||||
import * as blueslip from "./blueslip";
|
||||
import * as color_class from "./color_class";
|
||||
import * as hash_util from "./hash_util";
|
||||
import {$t} from "./i18n";
|
||||
import * as keydown_util from "./keydown_util";
|
||||
import {ListCursor} from "./list_cursor";
|
||||
import * as narrow from "./narrow";
|
||||
|
@ -100,10 +102,12 @@ export function create_initial_sidebar_rows() {
|
|||
}
|
||||
|
||||
export function build_stream_list(force_rerender) {
|
||||
// This function assumes we have already created the individual
|
||||
// sidebar rows. Our job here is to build the bigger widget,
|
||||
// which largely is a matter of arranging the individual rows in
|
||||
// the right order.
|
||||
// The stream list in the left sidebar contains 3 sections:
|
||||
// pinned, normal, and dormant streams, with headings above them
|
||||
// as appropriate.
|
||||
//
|
||||
// Within the first two sections, muted streams are sorted to the
|
||||
// bottom; we skip that for dormant streams to simplify discovery.
|
||||
const streams = stream_data.subscribed_stream_ids();
|
||||
const $parent = $("#stream_filters");
|
||||
if (streams.length === 0) {
|
||||
|
@ -112,7 +116,7 @@ export function build_stream_list(force_rerender) {
|
|||
}
|
||||
|
||||
// The main logic to build the list is in stream_sort.js, and
|
||||
// we get three lists of streams (pinned/normal/dormant).
|
||||
// we get five lists of streams (pinned/normal/muted_pinned/muted_normal/dormant).
|
||||
const stream_groups = stream_sort.sort_groups(streams, get_search_term());
|
||||
|
||||
if (stream_groups.same_as_before && !force_rerender) {
|
||||
|
@ -130,24 +134,54 @@ export function build_stream_list(force_rerender) {
|
|||
topic_list.clear();
|
||||
$parent.empty();
|
||||
|
||||
for (const stream_id of stream_groups.pinned_streams) {
|
||||
add_sidebar_li(stream_id);
|
||||
}
|
||||
|
||||
const any_pinned_streams = stream_groups.pinned_streams.length > 0;
|
||||
const any_normal_streams = stream_groups.normal_streams.length > 0;
|
||||
const any_dormant_streams = stream_groups.dormant_streams.length > 0;
|
||||
|
||||
if (any_pinned_streams && (any_normal_streams || any_dormant_streams)) {
|
||||
elems.push('<hr class="stream-split">');
|
||||
if (any_pinned_streams) {
|
||||
elems.push(
|
||||
render_stream_subheader({
|
||||
subheader_name: $t({
|
||||
defaultMessage: "Pinned",
|
||||
}),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
for (const stream_id of stream_groups.pinned_streams) {
|
||||
add_sidebar_li(stream_id);
|
||||
}
|
||||
|
||||
for (const stream_id of stream_groups.muted_pinned_streams) {
|
||||
add_sidebar_li(stream_id);
|
||||
}
|
||||
|
||||
if (any_normal_streams) {
|
||||
elems.push(
|
||||
render_stream_subheader({
|
||||
subheader_name: $t({
|
||||
defaultMessage: "Active",
|
||||
}),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
for (const stream_id of stream_groups.normal_streams) {
|
||||
add_sidebar_li(stream_id);
|
||||
}
|
||||
|
||||
if (any_dormant_streams && any_normal_streams) {
|
||||
elems.push('<hr class="stream-split">');
|
||||
for (const stream_id of stream_groups.muted_active_streams) {
|
||||
add_sidebar_li(stream_id);
|
||||
}
|
||||
|
||||
if (any_dormant_streams) {
|
||||
elems.push(
|
||||
render_stream_subheader({
|
||||
subheader_name: $t({
|
||||
defaultMessage: "Inactive",
|
||||
}),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
for (const stream_id of stream_groups.dormant_streams) {
|
||||
|
@ -195,7 +229,7 @@ export function zoom_in_topics(options) {
|
|||
$(".stream-filters-label").each(function () {
|
||||
$(this).hide();
|
||||
});
|
||||
$(".stream-split").each(function () {
|
||||
$(".streams_subheader").each(function () {
|
||||
$(this).hide();
|
||||
});
|
||||
|
||||
|
@ -216,7 +250,7 @@ export function zoom_out_topics() {
|
|||
$(".stream-filters-label").each(function () {
|
||||
$(this).show();
|
||||
});
|
||||
$(".stream-split").each(function () {
|
||||
$(".streams_subheader").each(function () {
|
||||
$(this).show();
|
||||
});
|
||||
|
||||
|
@ -376,6 +410,11 @@ export function refresh_pinned_or_unpinned_stream(sub) {
|
|||
}
|
||||
}
|
||||
|
||||
export function refresh_muted_or_unmuted_stream(sub) {
|
||||
build_stream_sidebar_row(sub);
|
||||
update_streams_sidebar();
|
||||
}
|
||||
|
||||
export function get_sidebar_stream_topic_info(filter) {
|
||||
const result = {
|
||||
stream_id: undefined,
|
||||
|
|
|
@ -5,6 +5,8 @@ import * as util from "./util";
|
|||
let previous_pinned;
|
||||
let previous_normal;
|
||||
let previous_dormant;
|
||||
let previous_muted_active;
|
||||
let previous_muted_pinned;
|
||||
let all_streams = [];
|
||||
|
||||
export function get_streams() {
|
||||
|
@ -41,15 +43,25 @@ export function sort_groups(streams, search_term) {
|
|||
|
||||
const pinned_streams = [];
|
||||
const normal_streams = [];
|
||||
const muted_pinned_streams = [];
|
||||
const muted_active_streams = [];
|
||||
const dormant_streams = [];
|
||||
|
||||
for (const stream of streams) {
|
||||
const sub = sub_store.get(stream);
|
||||
const pinned = sub.pin_to_top;
|
||||
if (pinned) {
|
||||
pinned_streams.push(stream);
|
||||
if (!sub.is_muted) {
|
||||
pinned_streams.push(stream);
|
||||
} else {
|
||||
muted_pinned_streams.push(stream);
|
||||
}
|
||||
} else if (is_normal(sub)) {
|
||||
normal_streams.push(stream);
|
||||
if (!sub.is_muted) {
|
||||
normal_streams.push(stream);
|
||||
} else {
|
||||
muted_active_streams.push(stream);
|
||||
}
|
||||
} else {
|
||||
dormant_streams.push(stream);
|
||||
}
|
||||
|
@ -57,20 +69,31 @@ export function sort_groups(streams, search_term) {
|
|||
|
||||
pinned_streams.sort(compare_function);
|
||||
normal_streams.sort(compare_function);
|
||||
muted_pinned_streams.sort(compare_function);
|
||||
muted_active_streams.sort(compare_function);
|
||||
dormant_streams.sort(compare_function);
|
||||
|
||||
const same_as_before =
|
||||
previous_pinned !== undefined &&
|
||||
util.array_compare(previous_pinned, pinned_streams) &&
|
||||
util.array_compare(previous_normal, normal_streams) &&
|
||||
util.array_compare(previous_muted_pinned, muted_pinned_streams) &&
|
||||
util.array_compare(previous_muted_active, muted_active_streams) &&
|
||||
util.array_compare(previous_dormant, dormant_streams);
|
||||
|
||||
if (!same_as_before) {
|
||||
previous_pinned = pinned_streams;
|
||||
previous_normal = normal_streams;
|
||||
previous_muted_pinned = muted_pinned_streams;
|
||||
previous_muted_active = muted_active_streams;
|
||||
previous_dormant = dormant_streams;
|
||||
|
||||
all_streams = pinned_streams.concat(normal_streams, dormant_streams);
|
||||
all_streams = pinned_streams.concat(
|
||||
muted_pinned_streams,
|
||||
normal_streams,
|
||||
muted_active_streams,
|
||||
dormant_streams,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -78,6 +101,8 @@ export function sort_groups(streams, search_term) {
|
|||
pinned_streams,
|
||||
normal_streams,
|
||||
dormant_streams,
|
||||
muted_pinned_streams,
|
||||
muted_active_streams,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1089,7 +1089,9 @@ body.dark-theme {
|
|||
.sub-unsub-message span::before,
|
||||
.sub-unsub-message span::after,
|
||||
.date_row span::before,
|
||||
.date_row span::after {
|
||||
.date_row span::after,
|
||||
.streams_subheader span::before,
|
||||
.streams_subheader span::after {
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
|
|
|
@ -169,6 +169,15 @@ li.show-more-topics {
|
|||
.inactive_stream {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.toggle_stream_mute {
|
||||
margin-right: 3px;
|
||||
opacity: 0.5;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.narrows_panel {
|
||||
|
@ -561,6 +570,42 @@ li.expanded_private_message {
|
|||
}
|
||||
}
|
||||
|
||||
.streams_subheader {
|
||||
font-size: 0.8em;
|
||||
font-weight: normal;
|
||||
padding-left: $far_left_gutter_size;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
margin-right: 12px;
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
left: 0.5em;
|
||||
right: 0.5em;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
span::before,
|
||||
span::after {
|
||||
content: " ";
|
||||
flex: 1 1;
|
||||
vertical-align: middle;
|
||||
margin: auto;
|
||||
border-top: 1px solid hsl(0, 0%, 88%);
|
||||
border-bottom: 1px solid hsl(0, 0%, 100%);
|
||||
}
|
||||
|
||||
span::before {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
span::after {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.stream-list-filter {
|
||||
width: 216px;
|
||||
white-space: nowrap;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<div class="streams_subheader">
|
||||
<span>{{ subheader_name }}</span>
|
||||
</div>
|
Loading…
Reference in New Issue