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; 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", })); }