mirror of https://github.com/zulip/zulip.git
stream_list: Convert module to typescript.
This commit is contained in:
parent
fda1afaaa7
commit
44b07094df
|
@ -234,7 +234,7 @@ EXEMPT_FILES = make_set(
|
||||||
"web/src/stream_edit.js",
|
"web/src/stream_edit.js",
|
||||||
"web/src/stream_edit_subscribers.js",
|
"web/src/stream_edit_subscribers.js",
|
||||||
"web/src/stream_edit_toggler.ts",
|
"web/src/stream_edit_toggler.ts",
|
||||||
"web/src/stream_list.js",
|
"web/src/stream_list.ts",
|
||||||
"web/src/stream_muting.js",
|
"web/src/stream_muting.js",
|
||||||
"web/src/stream_popover.js",
|
"web/src/stream_popover.js",
|
||||||
"web/src/stream_settings_api.ts",
|
"web/src/stream_settings_api.ts",
|
||||||
|
|
|
@ -14,7 +14,7 @@ import * as vdom from "./vdom";
|
||||||
let prior_dom: vdom.Tag<PMNode> | undefined;
|
let prior_dom: vdom.Tag<PMNode> | undefined;
|
||||||
|
|
||||||
// This module manages the direct messages section in the upper
|
// This module manages the direct messages section in the upper
|
||||||
// left corner of the app. This was split out from stream_list.js.
|
// left corner of the app. This was split out from stream_list.ts.
|
||||||
|
|
||||||
let private_messages_collapsed = false;
|
let private_messages_collapsed = false;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
import assert from "minimalistic-assert";
|
||||||
|
|
||||||
import render_filter_topics from "../templates/filter_topics.hbs";
|
import render_filter_topics from "../templates/filter_topics.hbs";
|
||||||
import render_stream_privacy from "../templates/stream_privacy.hbs";
|
import render_stream_privacy from "../templates/stream_privacy.hbs";
|
||||||
|
@ -8,6 +9,7 @@ import render_stream_subheader from "../templates/streams_subheader.hbs";
|
||||||
import render_subscribe_to_more_streams from "../templates/subscribe_to_more_streams.hbs";
|
import render_subscribe_to_more_streams from "../templates/subscribe_to_more_streams.hbs";
|
||||||
|
|
||||||
import * as blueslip from "./blueslip";
|
import * as blueslip from "./blueslip";
|
||||||
|
import type {Filter} from "./filter";
|
||||||
import * as hash_util from "./hash_util";
|
import * as hash_util from "./hash_util";
|
||||||
import {$t} from "./i18n";
|
import {$t} from "./i18n";
|
||||||
import * as keydown_util from "./keydown_util";
|
import * as keydown_util from "./keydown_util";
|
||||||
|
@ -22,22 +24,24 @@ import * as sidebar_ui from "./sidebar_ui";
|
||||||
import * as stream_data from "./stream_data";
|
import * as stream_data from "./stream_data";
|
||||||
import * as stream_list_sort from "./stream_list_sort";
|
import * as stream_list_sort from "./stream_list_sort";
|
||||||
import * as sub_store from "./sub_store";
|
import * as sub_store from "./sub_store";
|
||||||
|
import type {StreamSubscription} from "./sub_store";
|
||||||
import * as topic_list from "./topic_list";
|
import * as topic_list from "./topic_list";
|
||||||
import * as ui_util from "./ui_util";
|
import * as ui_util from "./ui_util";
|
||||||
import * as unread from "./unread";
|
import * as unread from "./unread";
|
||||||
|
import type {FullUnreadCountsData, StreamCountInfo} from "./unread";
|
||||||
|
|
||||||
let pending_stream_list_rerender = false;
|
let pending_stream_list_rerender = false;
|
||||||
let zoomed_in = false;
|
let zoomed_in = false;
|
||||||
|
|
||||||
export let stream_cursor;
|
export let stream_cursor: ListCursor<number>;
|
||||||
|
|
||||||
let has_scrolled = false;
|
let has_scrolled = false;
|
||||||
|
|
||||||
export function is_zoomed_in() {
|
export function is_zoomed_in(): boolean {
|
||||||
return zoomed_in;
|
return zoomed_in;
|
||||||
}
|
}
|
||||||
|
|
||||||
function zoom_in() {
|
function zoom_in(): void {
|
||||||
const stream_id = topic_list.active_stream_id();
|
const stream_id = topic_list.active_stream_id();
|
||||||
|
|
||||||
popovers.hide_all();
|
popovers.hide_all();
|
||||||
|
@ -50,11 +54,11 @@ function zoom_in() {
|
||||||
zoomed_in = true;
|
zoomed_in = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function set_pending_stream_list_rerender(value) {
|
export function set_pending_stream_list_rerender(value: boolean): void {
|
||||||
pending_stream_list_rerender = value;
|
pending_stream_list_rerender = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function zoom_out() {
|
export function zoom_out(): void {
|
||||||
if (pending_stream_list_rerender) {
|
if (pending_stream_list_rerender) {
|
||||||
update_streams_sidebar(true);
|
update_streams_sidebar(true);
|
||||||
}
|
}
|
||||||
|
@ -71,7 +75,7 @@ export function zoom_out() {
|
||||||
zoomed_in = false;
|
zoomed_in = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clear_topics() {
|
export function clear_topics(): void {
|
||||||
const $stream_li = topic_list.get_stream_li();
|
const $stream_li = topic_list.get_stream_li();
|
||||||
|
|
||||||
topic_list.close();
|
topic_list.close();
|
||||||
|
@ -88,12 +92,12 @@ export function clear_topics() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_count_in_dom(
|
export function update_count_in_dom(
|
||||||
$stream_li,
|
$stream_li: JQuery,
|
||||||
stream_counts,
|
stream_counts: StreamCountInfo,
|
||||||
stream_has_any_unread_mention_messages,
|
stream_has_any_unread_mention_messages: boolean,
|
||||||
stream_has_any_unmuted_unread_mention,
|
stream_has_any_unmuted_unread_mention: boolean,
|
||||||
stream_has_only_muted_unread_mention,
|
stream_has_only_muted_unread_mention: boolean,
|
||||||
) {
|
): void {
|
||||||
// The subscription_block properly excludes the topic list,
|
// The subscription_block properly excludes the topic list,
|
||||||
// and it also has sensitive margins related to whether the
|
// and it also has sensitive margins related to whether the
|
||||||
// count is there or not.
|
// count is there or not.
|
||||||
|
@ -171,19 +175,19 @@ export function update_count_in_dom(
|
||||||
class StreamSidebar {
|
class StreamSidebar {
|
||||||
rows = new Map(); // stream id -> row widget
|
rows = new Map(); // stream id -> row widget
|
||||||
|
|
||||||
set_row(stream_id, widget) {
|
set_row(stream_id: number, widget: StreamSidebarRow): void {
|
||||||
this.rows.set(stream_id, widget);
|
this.rows.set(stream_id, widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
get_row(stream_id) {
|
get_row(stream_id: number): StreamSidebarRow {
|
||||||
return this.rows.get(stream_id);
|
return this.rows.get(stream_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
has_row_for(stream_id) {
|
has_row_for(stream_id: number): boolean {
|
||||||
return this.rows.has(stream_id);
|
return this.rows.has(stream_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_row(stream_id) {
|
remove_row(stream_id: number): void {
|
||||||
// This only removes the row from our data structure.
|
// This only removes the row from our data structure.
|
||||||
// Our caller should use build_stream_list() to re-draw
|
// Our caller should use build_stream_list() to re-draw
|
||||||
// the sidebar, so that we don't have to deal with edge
|
// the sidebar, so that we don't have to deal with edge
|
||||||
|
@ -195,24 +199,25 @@ class StreamSidebar {
|
||||||
}
|
}
|
||||||
export const stream_sidebar = new StreamSidebar();
|
export const stream_sidebar = new StreamSidebar();
|
||||||
|
|
||||||
function get_search_term() {
|
function get_search_term(): string {
|
||||||
const $search_box = $(".stream-list-filter");
|
const $search_box = $<HTMLInputElement>(".stream-list-filter").expectOne();
|
||||||
const search_term = $search_box.expectOne().val().trim();
|
const search_term = $search_box.val();
|
||||||
return search_term;
|
assert(search_term !== undefined);
|
||||||
|
return search_term.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function add_sidebar_row(sub) {
|
export function add_sidebar_row(sub: StreamSubscription): void {
|
||||||
create_sidebar_row(sub);
|
create_sidebar_row(sub);
|
||||||
update_streams_sidebar();
|
update_streams_sidebar();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function remove_sidebar_row(stream_id) {
|
export function remove_sidebar_row(stream_id: number): void {
|
||||||
stream_sidebar.remove_row(stream_id);
|
stream_sidebar.remove_row(stream_id);
|
||||||
const force_rerender = stream_id === topic_list.active_stream_id();
|
const force_rerender = stream_id === topic_list.active_stream_id();
|
||||||
update_streams_sidebar(force_rerender);
|
update_streams_sidebar(force_rerender);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function create_initial_sidebar_rows() {
|
export function create_initial_sidebar_rows(): void {
|
||||||
// This code is slightly opaque, but it ends up building
|
// This code is slightly opaque, but it ends up building
|
||||||
// up list items and attaching them to the "sub" data
|
// up list items and attaching them to the "sub" data
|
||||||
// structures that are kept in stream_data.js.
|
// structures that are kept in stream_data.js.
|
||||||
|
@ -223,7 +228,7 @@ export function create_initial_sidebar_rows() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function build_stream_list(force_rerender) {
|
export function build_stream_list(force_rerender: boolean): void {
|
||||||
// The stream list in the left sidebar contains 3 sections:
|
// The stream list in the left sidebar contains 3 sections:
|
||||||
// pinned, normal, and dormant streams, with headings above them
|
// pinned, normal, and dormant streams, with headings above them
|
||||||
// as appropriate.
|
// as appropriate.
|
||||||
|
@ -247,7 +252,7 @@ export function build_stream_list(force_rerender) {
|
||||||
|
|
||||||
const elems = [];
|
const elems = [];
|
||||||
|
|
||||||
function add_sidebar_li(stream_id) {
|
function add_sidebar_li(stream_id: number): void {
|
||||||
const sidebar_row = stream_sidebar.get_row(stream_id);
|
const sidebar_row = stream_sidebar.get_row(stream_id);
|
||||||
sidebar_row.update_whether_active();
|
sidebar_row.update_whether_active();
|
||||||
elems.push(sidebar_row.get_li());
|
elems.push(sidebar_row.get_li());
|
||||||
|
@ -270,11 +275,13 @@ export function build_stream_list(force_rerender) {
|
||||||
|
|
||||||
if (any_pinned_streams && need_section_subheaders) {
|
if (any_pinned_streams && need_section_subheaders) {
|
||||||
elems.push(
|
elems.push(
|
||||||
|
$(
|
||||||
render_stream_subheader({
|
render_stream_subheader({
|
||||||
subheader_name: $t({
|
subheader_name: $t({
|
||||||
defaultMessage: "Pinned",
|
defaultMessage: "Pinned",
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,11 +295,13 @@ export function build_stream_list(force_rerender) {
|
||||||
|
|
||||||
if (any_normal_streams && need_section_subheaders) {
|
if (any_normal_streams && need_section_subheaders) {
|
||||||
elems.push(
|
elems.push(
|
||||||
|
$(
|
||||||
render_stream_subheader({
|
render_stream_subheader({
|
||||||
subheader_name: $t({
|
subheader_name: $t({
|
||||||
defaultMessage: "Active",
|
defaultMessage: "Active",
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,11 +315,13 @@ export function build_stream_list(force_rerender) {
|
||||||
|
|
||||||
if (any_dormant_streams && need_section_subheaders) {
|
if (any_dormant_streams && need_section_subheaders) {
|
||||||
elems.push(
|
elems.push(
|
||||||
|
$(
|
||||||
render_stream_subheader({
|
render_stream_subheader({
|
||||||
subheader_name: $t({
|
subheader_name: $t({
|
||||||
defaultMessage: "Inactive",
|
defaultMessage: "Inactive",
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,7 +332,7 @@ export function build_stream_list(force_rerender) {
|
||||||
$parent.append(elems);
|
$parent.append(elems);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_stream_li(stream_id) {
|
export function get_stream_li(stream_id: number): JQuery | undefined {
|
||||||
const row = stream_sidebar.get_row(stream_id);
|
const row = stream_sidebar.get_row(stream_id);
|
||||||
if (!row) {
|
if (!row) {
|
||||||
// Not all streams are in the sidebar, so we don't report
|
// Not all streams are in the sidebar, so we don't report
|
||||||
|
@ -344,7 +355,7 @@ export function get_stream_li(stream_id) {
|
||||||
return $li;
|
return $li;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_subscribe_to_more_streams_link() {
|
export function update_subscribe_to_more_streams_link(): void {
|
||||||
const can_subscribe_stream_count = stream_data
|
const can_subscribe_stream_count = stream_data
|
||||||
.unsubscribed_subs()
|
.unsubscribed_subs()
|
||||||
.filter((sub) => stream_data.can_toggle_subscription(sub)).length;
|
.filter((sub) => stream_data.can_toggle_subscription(sub)).length;
|
||||||
|
@ -363,11 +374,13 @@ export function update_subscribe_to_more_streams_link() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stream_id_for_elt($elt) {
|
function stream_id_for_elt($elt: JQuery): number {
|
||||||
return Number.parseInt($elt.attr("data-stream-id"), 10);
|
const stream_id_string = $elt.attr("data-stream-id");
|
||||||
|
assert(stream_id_string !== undefined);
|
||||||
|
return Number.parseInt(stream_id_string, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function zoom_in_topics(options) {
|
export function zoom_in_topics(options: {stream_id: number | undefined}): void {
|
||||||
// This only does stream-related tasks related to zooming
|
// This only does stream-related tasks related to zooming
|
||||||
// in to more topics, which is basically hiding all the
|
// in to more topics, which is basically hiding all the
|
||||||
// other streams.
|
// other streams.
|
||||||
|
@ -398,7 +411,7 @@ export function zoom_in_topics(options) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function zoom_out_topics() {
|
export function zoom_out_topics(): void {
|
||||||
// Show stream list titles and pinned stream splitter
|
// Show stream list titles and pinned stream splitter
|
||||||
$(".stream-filters-label").each(function () {
|
$(".stream-filters-label").each(function () {
|
||||||
$(this).show();
|
$(this).show();
|
||||||
|
@ -413,7 +426,7 @@ export function zoom_out_topics() {
|
||||||
$(".filter-topics").remove();
|
$(".filter-topics").remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function set_in_home_view(stream_id, in_home) {
|
export function set_in_home_view(stream_id: number, in_home: boolean): void {
|
||||||
const $li = get_stream_li(stream_id);
|
const $li = get_stream_li(stream_id);
|
||||||
if (!$li) {
|
if (!$li) {
|
||||||
blueslip.error("passed in bad stream id", {stream_id});
|
blueslip.error("passed in bad stream id", {stream_id});
|
||||||
|
@ -427,7 +440,7 @@ export function set_in_home_view(stream_id, in_home) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function build_stream_sidebar_li(sub) {
|
function build_stream_sidebar_li(sub: StreamSubscription): JQuery {
|
||||||
const name = sub.name;
|
const name = sub.name;
|
||||||
const is_muted = stream_data.is_muted(sub.stream_id);
|
const is_muted = stream_data.is_muted(sub.stream_id);
|
||||||
const args = {
|
const args = {
|
||||||
|
@ -446,13 +459,16 @@ function build_stream_sidebar_li(sub) {
|
||||||
}
|
}
|
||||||
|
|
||||||
class StreamSidebarRow {
|
class StreamSidebarRow {
|
||||||
constructor(sub) {
|
sub: StreamSubscription;
|
||||||
|
$list_item: JQuery;
|
||||||
|
|
||||||
|
constructor(sub: StreamSubscription) {
|
||||||
this.sub = sub;
|
this.sub = sub;
|
||||||
this.$list_item = build_stream_sidebar_li(sub);
|
this.$list_item = build_stream_sidebar_li(sub);
|
||||||
this.update_unread_count();
|
this.update_unread_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
update_whether_active() {
|
update_whether_active(): void {
|
||||||
if (stream_list_sort.has_recent_activity(this.sub) || this.sub.pin_to_top === true) {
|
if (stream_list_sort.has_recent_activity(this.sub) || this.sub.pin_to_top === true) {
|
||||||
this.$list_item.removeClass("inactive_stream");
|
this.$list_item.removeClass("inactive_stream");
|
||||||
} else {
|
} else {
|
||||||
|
@ -460,15 +476,15 @@ class StreamSidebarRow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get_li() {
|
get_li(): JQuery {
|
||||||
return this.$list_item;
|
return this.$list_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
remove() {
|
remove(): void {
|
||||||
this.$list_item.remove();
|
this.$list_item.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
update_unread_count() {
|
update_unread_count(): void {
|
||||||
const count = unread.unread_count_info_for_stream(this.sub.stream_id);
|
const count = unread.unread_count_info_for_stream(this.sub.stream_id);
|
||||||
const stream_has_any_unread_mention_messages = unread.stream_has_any_unread_mentions(
|
const stream_has_any_unread_mention_messages = unread.stream_has_any_unread_mentions(
|
||||||
this.sub.stream_id,
|
this.sub.stream_id,
|
||||||
|
@ -490,11 +506,11 @@ class StreamSidebarRow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function build_stream_sidebar_row(sub) {
|
function build_stream_sidebar_row(sub: StreamSubscription): void {
|
||||||
stream_sidebar.set_row(sub.stream_id, new StreamSidebarRow(sub));
|
stream_sidebar.set_row(sub.stream_id, new StreamSidebarRow(sub));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function create_sidebar_row(sub) {
|
export function create_sidebar_row(sub: StreamSubscription): void {
|
||||||
if (stream_sidebar.has_row_for(sub.stream_id)) {
|
if (stream_sidebar.has_row_for(sub.stream_id)) {
|
||||||
// already exists
|
// already exists
|
||||||
blueslip.warn("Dup try to build sidebar row for stream", {stream_id: sub.stream_id});
|
blueslip.warn("Dup try to build sidebar row for stream", {stream_id: sub.stream_id});
|
||||||
|
@ -503,7 +519,7 @@ export function create_sidebar_row(sub) {
|
||||||
build_stream_sidebar_row(sub);
|
build_stream_sidebar_row(sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function redraw_stream_privacy(sub) {
|
export function redraw_stream_privacy(sub: StreamSubscription): void {
|
||||||
const $li = get_stream_li(sub.stream_id);
|
const $li = get_stream_li(sub.stream_id);
|
||||||
if (!$li) {
|
if (!$li) {
|
||||||
// We don't want to raise error here, if we can't find stream in subscription
|
// We don't want to raise error here, if we can't find stream in subscription
|
||||||
|
@ -524,12 +540,12 @@ export function redraw_stream_privacy(sub) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_stream_unread_count(
|
function set_stream_unread_count(
|
||||||
stream_id,
|
stream_id: number,
|
||||||
count,
|
count: StreamCountInfo,
|
||||||
stream_has_any_unread_mention_messages,
|
stream_has_any_unread_mention_messages: boolean,
|
||||||
stream_has_any_unmuted_unread_mention,
|
stream_has_any_unmuted_unread_mention: boolean,
|
||||||
stream_has_only_muted_unread_mentions,
|
stream_has_only_muted_unread_mentions: boolean,
|
||||||
) {
|
): void {
|
||||||
const $stream_li = get_stream_li(stream_id);
|
const $stream_li = get_stream_li(stream_id);
|
||||||
if (!$stream_li) {
|
if (!$stream_li) {
|
||||||
// This can happen for legitimate reasons, but we warn
|
// This can happen for legitimate reasons, but we warn
|
||||||
|
@ -546,13 +562,14 @@ function set_stream_unread_count(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_streams_sidebar(force_rerender) {
|
export function update_streams_sidebar(force_rerender = false): void {
|
||||||
if (!force_rerender && is_zoomed_in()) {
|
if (!force_rerender && is_zoomed_in()) {
|
||||||
// We do our best to update topics that are displayed
|
// We do our best to update topics that are displayed
|
||||||
// in case user zoomed in. Streams list will be updated,
|
// in case user zoomed in. Streams list will be updated,
|
||||||
// once the user zooms out. This avoids user being zoomed out
|
// once the user zooms out. This avoids user being zoomed out
|
||||||
// when a new message causes streams to re-arrange.
|
// when a new message causes streams to re-arrange.
|
||||||
const filter = narrow_state.filter();
|
const filter = narrow_state.filter();
|
||||||
|
assert(filter !== undefined);
|
||||||
update_stream_sidebar_for_narrow(filter);
|
update_stream_sidebar_for_narrow(filter);
|
||||||
set_pending_stream_list_rerender(true);
|
set_pending_stream_list_rerender(true);
|
||||||
return;
|
return;
|
||||||
|
@ -568,19 +585,21 @@ export function update_streams_sidebar(force_rerender) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const filter = narrow_state.filter();
|
const filter = narrow_state.filter();
|
||||||
|
assert(filter !== undefined);
|
||||||
update_stream_sidebar_for_narrow(filter);
|
update_stream_sidebar_for_narrow(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_dom_with_unread_counts(counts) {
|
export function update_dom_with_unread_counts(counts: FullUnreadCountsData): void {
|
||||||
// counts.stream_count maps streams to counts
|
// counts.stream_count maps streams to counts
|
||||||
for (const [stream_id, count] of counts.stream_count) {
|
for (const [stream_id, count] of counts.stream_count) {
|
||||||
const stream_has_any_unread_mention_messages =
|
const stream_has_any_unread_mention_messages =
|
||||||
counts.streams_with_mentions.includes(stream_id);
|
counts.streams_with_mentions.includes(stream_id);
|
||||||
const stream_has_any_unmuted_unread_mention =
|
const stream_has_any_unmuted_unread_mention =
|
||||||
counts.streams_with_unmuted_mentions.includes(stream_id);
|
counts.streams_with_unmuted_mentions.includes(stream_id);
|
||||||
|
const sub = sub_store.get(stream_id);
|
||||||
|
assert(sub !== undefined);
|
||||||
const stream_has_only_muted_unread_mentions =
|
const stream_has_only_muted_unread_mentions =
|
||||||
!sub_store.get(stream_id).is_muted &&
|
!sub.is_muted &&
|
||||||
stream_has_any_unread_mention_messages &&
|
stream_has_any_unread_mention_messages &&
|
||||||
!stream_has_any_unmuted_unread_mention;
|
!stream_has_any_unmuted_unread_mention;
|
||||||
set_stream_unread_count(
|
set_stream_unread_count(
|
||||||
|
@ -593,9 +612,9 @@ export function update_dom_with_unread_counts(counts) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_dom_unread_counts_visibility() {
|
export function update_dom_unread_counts_visibility(): void {
|
||||||
const $streams_header = $("#streams_header");
|
const $streams_header = $("#streams_header");
|
||||||
if (settings_data.should_mask_unread_count()) {
|
if (settings_data.should_mask_unread_count(false)) {
|
||||||
$streams_header.addClass("hide_unread_counts");
|
$streams_header.addClass("hide_unread_counts");
|
||||||
} else {
|
} else {
|
||||||
$streams_header.removeClass("hide_unread_counts");
|
$streams_header.removeClass("hide_unread_counts");
|
||||||
|
@ -614,13 +633,13 @@ export function update_dom_unread_counts_visibility() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function rename_stream(sub) {
|
export function rename_stream(sub: StreamSubscription): void {
|
||||||
// The sub object is expected to already have the updated name
|
// The sub object is expected to already have the updated name
|
||||||
build_stream_sidebar_row(sub);
|
build_stream_sidebar_row(sub);
|
||||||
update_streams_sidebar(true); // big hammer
|
update_streams_sidebar(true); // big hammer
|
||||||
}
|
}
|
||||||
|
|
||||||
export function refresh_pinned_or_unpinned_stream(sub) {
|
export function refresh_pinned_or_unpinned_stream(sub: StreamSubscription): void {
|
||||||
// Pinned/unpinned streams require re-ordering.
|
// Pinned/unpinned streams require re-ordering.
|
||||||
// We use kind of brute force now, which is probably fine.
|
// We use kind of brute force now, which is probably fine.
|
||||||
build_stream_sidebar_row(sub);
|
build_stream_sidebar_row(sub);
|
||||||
|
@ -639,13 +658,19 @@ export function refresh_pinned_or_unpinned_stream(sub) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function refresh_muted_or_unmuted_stream(sub) {
|
export function refresh_muted_or_unmuted_stream(sub: StreamSubscription): void {
|
||||||
build_stream_sidebar_row(sub);
|
build_stream_sidebar_row(sub);
|
||||||
update_streams_sidebar();
|
update_streams_sidebar();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_sidebar_stream_topic_info(filter) {
|
export function get_sidebar_stream_topic_info(filter: Filter): {
|
||||||
const result = {
|
stream_id?: number;
|
||||||
|
topic_selected: boolean;
|
||||||
|
} {
|
||||||
|
const result: {
|
||||||
|
stream_id?: number;
|
||||||
|
topic_selected: boolean;
|
||||||
|
} = {
|
||||||
stream_id: undefined,
|
stream_id: undefined,
|
||||||
topic_selected: false,
|
topic_selected: false,
|
||||||
};
|
};
|
||||||
|
@ -674,11 +699,11 @@ export function get_sidebar_stream_topic_info(filter) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function deselect_stream_items() {
|
function deselect_stream_items(): void {
|
||||||
$("ul#stream_filters li").removeClass("active-filter stream-expanded");
|
$("ul#stream_filters li").removeClass("active-filter stream-expanded");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_stream_sidebar_for_narrow(filter) {
|
export function update_stream_sidebar_for_narrow(filter: Filter): JQuery | undefined {
|
||||||
const info = get_sidebar_stream_topic_info(filter);
|
const info = get_sidebar_stream_topic_info(filter);
|
||||||
|
|
||||||
deselect_stream_items();
|
deselect_stream_items();
|
||||||
|
@ -721,24 +746,24 @@ export function update_stream_sidebar_for_narrow(filter) {
|
||||||
return $stream_li;
|
return $stream_li;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handle_narrow_activated(filter) {
|
export function handle_narrow_activated(filter: Filter): void {
|
||||||
const $stream_li = update_stream_sidebar_for_narrow(filter);
|
const $stream_li = update_stream_sidebar_for_narrow(filter);
|
||||||
if ($stream_li) {
|
if ($stream_li) {
|
||||||
scroll_stream_into_view($stream_li);
|
scroll_stream_into_view($stream_li);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handle_message_view_deactivated() {
|
export function handle_message_view_deactivated(): void {
|
||||||
deselect_stream_items();
|
deselect_stream_items();
|
||||||
clear_topics();
|
clear_topics();
|
||||||
}
|
}
|
||||||
|
|
||||||
function focus_stream_filter(e) {
|
function focus_stream_filter(e: JQuery.ClickEvent): void {
|
||||||
stream_cursor.reset();
|
stream_cursor.reset();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
function actually_update_streams_for_search() {
|
function actually_update_streams_for_search(): void {
|
||||||
update_streams_sidebar();
|
update_streams_sidebar();
|
||||||
resize.resize_page_components();
|
resize.resize_page_components();
|
||||||
stream_cursor.reset();
|
stream_cursor.reset();
|
||||||
|
@ -747,7 +772,7 @@ function actually_update_streams_for_search() {
|
||||||
const update_streams_for_search = _.throttle(actually_update_streams_for_search, 50);
|
const update_streams_for_search = _.throttle(actually_update_streams_for_search, 50);
|
||||||
|
|
||||||
// Exported for tests only.
|
// Exported for tests only.
|
||||||
export function initialize_stream_cursor() {
|
export function initialize_stream_cursor(): void {
|
||||||
stream_cursor = new ListCursor({
|
stream_cursor = new ListCursor({
|
||||||
list: {
|
list: {
|
||||||
scroll_container_selector: "#left_sidebar_scroll_container",
|
scroll_container_selector: "#left_sidebar_scroll_container",
|
||||||
|
@ -764,7 +789,11 @@ export function initialize_stream_cursor() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initialize({on_stream_click}) {
|
export function initialize({
|
||||||
|
on_stream_click,
|
||||||
|
}: {
|
||||||
|
on_stream_click: (stream_id: number, trigger: string) => void;
|
||||||
|
}): void {
|
||||||
create_initial_sidebar_rows();
|
create_initial_sidebar_rows();
|
||||||
|
|
||||||
// We build the stream_list now. It may get re-built again very shortly
|
// We build the stream_list now. It may get re-built again very shortly
|
||||||
|
@ -789,7 +818,11 @@ export function initialize({on_stream_click}) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function set_event_handlers({on_stream_click}) {
|
export function set_event_handlers({
|
||||||
|
on_stream_click,
|
||||||
|
}: {
|
||||||
|
on_stream_click: (stream_id: number, trigger: string) => void;
|
||||||
|
}): void {
|
||||||
$("#stream_filters").on("click", "li .subscription_block", (e) => {
|
$("#stream_filters").on("click", "li .subscription_block", (e) => {
|
||||||
if (e.metaKey || e.ctrlKey) {
|
if (e.metaKey || e.ctrlKey) {
|
||||||
return;
|
return;
|
||||||
|
@ -815,7 +848,7 @@ export function set_event_handlers({on_stream_click}) {
|
||||||
toggle_filter_displayed(e);
|
toggle_filter_displayed(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
function toggle_pm_header_icon() {
|
function toggle_pm_header_icon(): void {
|
||||||
if (pm_list.is_private_messages_collapsed()) {
|
if (pm_list.is_private_messages_collapsed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -824,6 +857,8 @@ export function set_event_handlers({on_stream_click}) {
|
||||||
"#left_sidebar_scroll_container .simplebar-content-wrapper",
|
"#left_sidebar_scroll_container .simplebar-content-wrapper",
|
||||||
).scrollTop();
|
).scrollTop();
|
||||||
const pm_list_height = $("#direct-messages-list").height();
|
const pm_list_height = $("#direct-messages-list").height();
|
||||||
|
assert(scroll_position !== undefined);
|
||||||
|
assert(pm_list_height !== undefined);
|
||||||
if (scroll_position > pm_list_height) {
|
if (scroll_position > pm_list_height) {
|
||||||
$("#toggle_private_messages_section_icon").addClass("fa-caret-right");
|
$("#toggle_private_messages_section_icon").addClass("fa-caret-right");
|
||||||
$("#toggle_private_messages_section_icon").removeClass("fa-caret-down");
|
$("#toggle_private_messages_section_icon").removeClass("fa-caret-down");
|
||||||
|
@ -841,7 +876,7 @@ export function set_event_handlers({on_stream_click}) {
|
||||||
|
|
||||||
const $search_input = $(".stream-list-filter").expectOne();
|
const $search_input = $(".stream-list-filter").expectOne();
|
||||||
|
|
||||||
function keydown_enter_key() {
|
function keydown_enter_key(): void {
|
||||||
const stream_id = stream_cursor.get_key();
|
const stream_id = stream_cursor.get_key();
|
||||||
|
|
||||||
if (stream_id === undefined) {
|
if (stream_id === undefined) {
|
||||||
|
@ -872,15 +907,17 @@ export function set_event_handlers({on_stream_click}) {
|
||||||
});
|
});
|
||||||
|
|
||||||
$search_input.on("click", focus_stream_filter);
|
$search_input.on("click", focus_stream_filter);
|
||||||
$search_input.on("focusout", () => stream_cursor.clear());
|
$search_input.on("focusout", () => {
|
||||||
|
stream_cursor.clear();
|
||||||
|
});
|
||||||
$search_input.on("input", update_streams_for_search);
|
$search_input.on("input", update_streams_for_search);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function searching() {
|
export function searching(): boolean {
|
||||||
return $(".stream-list-filter").expectOne().is(":focus");
|
return $(".stream-list-filter").expectOne().is(":focus");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clear_search(e) {
|
export function clear_search(e: JQuery.ClickEvent): void {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const $filter = $(".stream-list-filter").expectOne();
|
const $filter = $(".stream-list-filter").expectOne();
|
||||||
if ($filter.val() === "") {
|
if ($filter.val() === "") {
|
||||||
|
@ -892,19 +929,19 @@ export function clear_search(e) {
|
||||||
update_streams_for_search();
|
update_streams_for_search();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function show_search_section() {
|
export function show_search_section(): void {
|
||||||
$("#streams_header").addClass("showing-stream-search-section");
|
$("#streams_header").addClass("showing-stream-search-section");
|
||||||
$(".stream_search_section").expectOne().removeClass("notdisplayed");
|
$(".stream_search_section").expectOne().removeClass("notdisplayed");
|
||||||
resize.resize_stream_filters_container();
|
resize.resize_stream_filters_container();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hide_search_section() {
|
export function hide_search_section(): void {
|
||||||
$("#streams_header").removeClass("showing-stream-search-section");
|
$("#streams_header").removeClass("showing-stream-search-section");
|
||||||
$(".stream_search_section").expectOne().addClass("notdisplayed");
|
$(".stream_search_section").expectOne().addClass("notdisplayed");
|
||||||
resize.resize_stream_filters_container();
|
resize.resize_stream_filters_container();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initiate_search() {
|
export function initiate_search(): void {
|
||||||
popovers.hide_all();
|
popovers.hide_all();
|
||||||
show_search_section();
|
show_search_section();
|
||||||
|
|
||||||
|
@ -923,7 +960,7 @@ export function initiate_search() {
|
||||||
stream_cursor.reset();
|
stream_cursor.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clear_and_hide_search() {
|
export function clear_and_hide_search(): void {
|
||||||
const $filter = $(".stream-list-filter").expectOne();
|
const $filter = $(".stream-list-filter").expectOne();
|
||||||
if ($filter.val() !== "") {
|
if ($filter.val() !== "") {
|
||||||
$filter.val("");
|
$filter.val("");
|
||||||
|
@ -935,7 +972,7 @@ export function clear_and_hide_search() {
|
||||||
hide_search_section();
|
hide_search_section();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toggle_filter_displayed(e) {
|
export function toggle_filter_displayed(e: JQuery.ClickEvent): void {
|
||||||
if ($(".stream_search_section.notdisplayed").length === 0) {
|
if ($(".stream_search_section.notdisplayed").length === 0) {
|
||||||
clear_and_hide_search();
|
clear_and_hide_search();
|
||||||
} else {
|
} else {
|
||||||
|
@ -944,7 +981,7 @@ export function toggle_filter_displayed(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function scroll_stream_into_view($stream_li) {
|
export function scroll_stream_into_view($stream_li: JQuery): void {
|
||||||
const $container = $("#left_sidebar_scroll_container");
|
const $container = $("#left_sidebar_scroll_container");
|
||||||
|
|
||||||
if ($stream_li.length !== 1) {
|
if ($stream_li.length !== 1) {
|
||||||
|
@ -955,7 +992,7 @@ export function scroll_stream_into_view($stream_li) {
|
||||||
scroll_util.scroll_element_into_container($stream_li, $container, stream_header_height);
|
scroll_util.scroll_element_into_container($stream_li, $container, stream_header_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function maybe_scroll_narrow_into_view() {
|
export function maybe_scroll_narrow_into_view(): void {
|
||||||
// we don't want to interfere with user scrolling once the page loads
|
// we don't want to interfere with user scrolling once the page loads
|
||||||
if (has_scrolled) {
|
if (has_scrolled) {
|
||||||
return;
|
return;
|
||||||
|
@ -967,7 +1004,7 @@ export function maybe_scroll_narrow_into_view() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_current_stream_li() {
|
export function get_current_stream_li(): JQuery | undefined {
|
||||||
const stream_id = topic_list.active_stream_id();
|
const stream_id = topic_list.active_stream_id();
|
||||||
|
|
||||||
if (!stream_id) {
|
if (!stream_id) {
|
|
@ -50,7 +50,7 @@ const unread_messages = new Set<number>();
|
||||||
// for how we can refresh it efficiently.
|
// for how we can refresh it efficiently.
|
||||||
export const unread_mention_topics = new Map();
|
export const unread_mention_topics = new Map();
|
||||||
|
|
||||||
type StreamCountInfo = {
|
export type StreamCountInfo = {
|
||||||
unmuted_count: number;
|
unmuted_count: number;
|
||||||
muted_count: number;
|
muted_count: number;
|
||||||
followed_count: number;
|
followed_count: number;
|
||||||
|
|
|
@ -162,9 +162,9 @@ test_ui("create_sidebar_row", ({override_rewire, mock_template}) => {
|
||||||
|
|
||||||
assert.ok(topics_closed);
|
assert.ok(topics_closed);
|
||||||
const expected_elems = [
|
const expected_elems = [
|
||||||
$pinned_subheader.html(), // separator
|
$pinned_subheader, // separator
|
||||||
$devel_sidebar, // pinned
|
$devel_sidebar, // pinned
|
||||||
$active_subheader.html(), // separator
|
$active_subheader, // separator
|
||||||
$social_sidebar, // not pinned
|
$social_sidebar, // not pinned
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -507,14 +507,14 @@ test_ui("sort_streams", ({override_rewire, mock_template}) => {
|
||||||
const $active_subheader = $("<active-subheader-stub>");
|
const $active_subheader = $("<active-subheader-stub>");
|
||||||
const $inactive_subheader = $("<inactive-subheader-stub>");
|
const $inactive_subheader = $("<inactive-subheader-stub>");
|
||||||
const expected_elems = [
|
const expected_elems = [
|
||||||
$pinned_subheader.html(),
|
$pinned_subheader,
|
||||||
$("<devel-sidebar-row-stub>"),
|
$("<devel-sidebar-row-stub>"),
|
||||||
$("<Rome-sidebar-row-stub>"),
|
$("<Rome-sidebar-row-stub>"),
|
||||||
$("<test-sidebar-row-stub>"),
|
$("<test-sidebar-row-stub>"),
|
||||||
$active_subheader.html(),
|
$active_subheader,
|
||||||
$("<announce-sidebar-row-stub>"),
|
$("<announce-sidebar-row-stub>"),
|
||||||
$("<Denmark-sidebar-row-stub>"),
|
$("<Denmark-sidebar-row-stub>"),
|
||||||
$inactive_subheader.html(),
|
$inactive_subheader,
|
||||||
$("<cars-sidebar-row-stub>"),
|
$("<cars-sidebar-row-stub>"),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -594,10 +594,10 @@ test_ui("separators_only_pinned_and_dormant", ({override_rewire, mock_template})
|
||||||
const $pinned_subheader = $("<pinned-subheader-stub>");
|
const $pinned_subheader = $("<pinned-subheader-stub>");
|
||||||
const $inactive_subheader = $("<inactive-subheader-stub>");
|
const $inactive_subheader = $("<inactive-subheader-stub>");
|
||||||
const expected_elems = [
|
const expected_elems = [
|
||||||
$pinned_subheader.html(), // pinned
|
$pinned_subheader, // pinned
|
||||||
$("<devel-sidebar-row-stub>"),
|
$("<devel-sidebar-row-stub>"),
|
||||||
$("<Rome-sidebar-row-stub>"),
|
$("<Rome-sidebar-row-stub>"),
|
||||||
$inactive_subheader.html(), // dormant
|
$inactive_subheader, // dormant
|
||||||
$("<Denmark-sidebar-row-stub>"),
|
$("<Denmark-sidebar-row-stub>"),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ const {run_test, noop} = require("./lib/test");
|
||||||
const $ = require("./lib/zjquery");
|
const $ = require("./lib/zjquery");
|
||||||
|
|
||||||
// This tests the stream searching functionality which currently
|
// This tests the stream searching functionality which currently
|
||||||
// lives in stream_list.js.
|
// lives in stream_list.ts.
|
||||||
|
|
||||||
mock_esm("../src/resize", {
|
mock_esm("../src/resize", {
|
||||||
resize_page_components: noop,
|
resize_page_components: noop,
|
||||||
|
|
Loading…
Reference in New Issue