zulip/web/src/stream_pill.ts
vivek-tripathi-9005 c032bd9e78 streams: Move subscriber count from channel pills to channel cards.
Previously, the number of subscribers was displayed on channel pills.

This commit removes the subscriber count from the channel pills and
adds it to the channel cards. The count is styled similarly to the
number of group members in group cards, with the text 'N subscribers'
(or '1 subscriber' for single subscribers).

Fixes: #32235.
2024-11-16 10:49:29 -08:00

133 lines
4.0 KiB
TypeScript

import assert from "minimalistic-assert";
import render_input_pill from "../templates/input_pill.hbs";
import type {InputPillContainer} from "./input_pill.ts";
import * as peer_data from "./peer_data.ts";
import * as stream_data from "./stream_data.ts";
import type {StreamSubscription} from "./sub_store.ts";
import type {CombinedPill, CombinedPillContainer} from "./typeahead_helper.ts";
export type StreamPill = {
type: "stream";
stream_id: number;
show_subscriber_count: boolean;
};
export type StreamPillWidget = InputPillContainer<StreamPill>;
export type StreamPillData = StreamSubscription & {type: "stream"};
export function create_item_from_stream_name(
stream_name: string,
current_items: CombinedPill[],
stream_prefix_required = true,
get_allowed_streams: () => StreamSubscription[] = stream_data.get_unsorted_subs,
show_subscriber_count = true,
): StreamPill | undefined {
stream_name = stream_name.trim();
if (stream_prefix_required) {
if (!stream_name.startsWith("#")) {
return undefined;
}
stream_name = stream_name.slice(1);
}
const sub = stream_data.get_sub(stream_name);
if (!sub) {
return undefined;
}
const streams = get_allowed_streams();
if (!streams.includes(sub)) {
return undefined;
}
if (current_items.some((item) => item.type === "stream" && item.stream_id === sub.stream_id)) {
return undefined;
}
return {
type: "stream",
show_subscriber_count,
stream_id: sub.stream_id,
};
}
export function get_stream_name_from_item(item: StreamPill): string {
const stream = stream_data.get_sub_by_id(item.stream_id);
assert(stream !== undefined);
return stream.name;
}
export function get_user_ids(pill_widget: StreamPillWidget | CombinedPillContainer): number[] {
let user_ids = pill_widget
.items()
.flatMap((item) =>
item.type === "stream" ? peer_data.get_subscribers(item.stream_id) : [],
);
user_ids = [...new Set(user_ids)];
user_ids.sort((a, b) => a - b);
return user_ids;
}
export function get_display_value_from_item(item: StreamPill): string {
const stream = stream_data.get_sub_by_id(item.stream_id);
assert(stream !== undefined);
return stream.name;
}
export function generate_pill_html(item: StreamPill): string {
const stream = stream_data.get_sub_by_id(item.stream_id);
assert(stream !== undefined);
return render_input_pill({
has_stream: true,
stream,
display_value: get_display_value_from_item(item),
stream_id: item.stream_id,
});
}
export function append_stream(
stream: StreamSubscription,
pill_widget: StreamPillWidget | CombinedPillContainer,
show_subscriber_count = true,
): void {
pill_widget.appendValidatedData({
type: "stream",
show_subscriber_count,
stream_id: stream.stream_id,
});
pill_widget.clear_text();
}
export function get_stream_ids(pill_widget: StreamPillWidget | CombinedPillContainer): number[] {
const items = pill_widget.items();
return items.flatMap((item) => (item.type === "stream" ? item.stream_id : []));
}
export function filter_taken_streams(
items: StreamSubscription[],
pill_widget: StreamPillWidget | CombinedPillContainer,
): StreamSubscription[] {
const taken_stream_ids = get_stream_ids(pill_widget);
items = items.filter((item) => !taken_stream_ids.includes(item.stream_id));
return items;
}
export function typeahead_source(
pill_widget: StreamPillWidget | CombinedPillContainer,
invite_streams?: boolean,
): StreamPillData[] {
const potential_streams = invite_streams
? stream_data.get_invite_stream_data()
: stream_data.get_unsorted_subs();
const active_streams = potential_streams.filter((sub) => !sub.is_archived);
return filter_taken_streams(active_streams, pill_widget).map((stream) => ({
...stream,
type: "stream",
}));
}