stream_events: Convert module to typescript.

This commit is contained in:
evykassirer
2024-11-24 23:35:23 -08:00
committed by Tim Abbott
parent c1cd21d8d1
commit 64c8884487
4 changed files with 112 additions and 50 deletions

View File

@@ -73,7 +73,7 @@ import * as starred_messages from "./starred_messages.ts";
import * as starred_messages_ui from "./starred_messages_ui.ts"; import * as starred_messages_ui from "./starred_messages_ui.ts";
import {current_user, realm} from "./state_data.ts"; import {current_user, realm} from "./state_data.ts";
import * as stream_data from "./stream_data.ts"; import * as stream_data from "./stream_data.ts";
import * as stream_events from "./stream_events.js"; import * as stream_events from "./stream_events.ts";
import * as stream_list from "./stream_list.ts"; import * as stream_list from "./stream_list.ts";
import * as stream_list_sort from "./stream_list_sort.ts"; import * as stream_list_sort from "./stream_list_sort.ts";
import * as stream_settings_ui from "./stream_settings_ui.ts"; import * as stream_settings_ui from "./stream_settings_ui.ts";

View File

@@ -28,6 +28,7 @@ import * as stream_muting from "./stream_muting.ts";
import * as stream_settings_api from "./stream_settings_api.ts"; import * as stream_settings_api from "./stream_settings_api.ts";
import * as stream_settings_ui from "./stream_settings_ui.ts"; import * as stream_settings_ui from "./stream_settings_ui.ts";
import * as sub_store from "./sub_store.ts"; import * as sub_store from "./sub_store.ts";
import type {StreamSubscription} from "./sub_store.ts";
import * as unread_ui from "./unread_ui.ts"; import * as unread_ui from "./unread_ui.ts";
import * as user_profile from "./user_profile.ts"; import * as user_profile from "./user_profile.ts";
@@ -35,13 +36,39 @@ import * as user_profile from "./user_profile.ts";
// however, they are only called after a manual override, so // however, they are only called after a manual override, so
// doing so is unnecessary with the current code. Ideally, we'd do a // doing so is unnecessary with the current code. Ideally, we'd do a
// refactor to address that, however. // refactor to address that, however.
function update_stream_setting(sub, value, setting) { function update_stream_setting(
const $setting_checkbox = $(`#${CSS.escape(setting)}_${CSS.escape(sub.stream_id)}`); sub: StreamSubscription,
value: boolean | null,
setting:
| "desktop_notifications"
| "audible_notifications"
| "push_notifications"
| "email_notifications"
| "wildcard_mentions_notify"
| "pin_to_top",
): void {
const $setting_checkbox = $(`#${CSS.escape(setting)}_${CSS.escape(sub.stream_id.toString())}`);
$setting_checkbox.prop("checked", value); $setting_checkbox.prop("checked", value);
if (setting === "pin_to_top") {
assert(value !== null);
sub[setting] = value;
return;
}
sub[setting] = value; sub[setting] = value;
} }
export function update_property(stream_id, property, value, other_values) { type UpdatableStreamProperties = sub_store.ApiStreamSubscription & {in_home_view: boolean};
export function update_property<P extends keyof UpdatableStreamProperties>(
stream_id: number,
property: P,
value: UpdatableStreamProperties[P],
other_values?: {
rendered_description: string;
history_public_to_subscribers: boolean;
is_web_public: boolean;
},
): void {
const sub = sub_store.get(stream_id); const sub = sub_store.get(stream_id);
if (sub === undefined) { if (sub === undefined) {
// This isn't a stream we know about, so ignore it. // This isn't a stream we know about, so ignore it.
@@ -53,63 +80,78 @@ export function update_property(stream_id, property, value, other_values) {
return; return;
} }
switch (property) { const update_stream_specific_notification_setting =
case "color": (property: keyof sub_store.StreamSpecificNotificationSettings) =>
(value: boolean | null) => {
update_stream_setting(sub, value, property);
assert(settings_notifications.user_settings_panel !== undefined);
settings_notifications.update_page(settings_notifications.user_settings_panel);
};
const updaters: {
[P in keyof UpdatableStreamProperties]?: (value: UpdatableStreamProperties[P]) => void;
} = {
color(value) {
stream_color_events.update_stream_color(sub, value); stream_color_events.update_stream_color(sub, value);
break; },
case "in_home_view": in_home_view(_value) {
// Legacy in_home_view events are only sent as duplicates of // Legacy in_home_view events are only sent as duplicates of
// modern is_muted events, which we handle below. // modern is_muted events, which we handle below.
break; },
case "is_muted": is_muted(value) {
stream_muting.update_is_muted(sub, value); stream_muting.update_is_muted(sub, value);
stream_list.refresh_muted_or_unmuted_stream(sub); stream_list.refresh_muted_or_unmuted_stream(sub);
recent_view_ui.complete_rerender(); recent_view_ui.complete_rerender();
break; },
case "desktop_notifications": desktop_notifications: update_stream_specific_notification_setting("desktop_notifications"),
case "audible_notifications": audible_notifications: update_stream_specific_notification_setting("audible_notifications"),
case "push_notifications": push_notifications: update_stream_specific_notification_setting("push_notifications"),
case "email_notifications": email_notifications: update_stream_specific_notification_setting("email_notifications"),
case "wildcard_mentions_notify": wildcard_mentions_notify: update_stream_specific_notification_setting(
update_stream_setting(sub, value, property); "wildcard_mentions_notify",
settings_notifications.update_page(settings_notifications.user_settings_panel); ),
break; name(value) {
case "name":
stream_settings_ui.update_stream_name(sub, value); stream_settings_ui.update_stream_name(sub, value);
compose_recipient.possibly_update_stream_name_in_compose(sub.stream_id); compose_recipient.possibly_update_stream_name_in_compose(sub.stream_id);
break; },
case "description": description(value) {
assert(other_values !== undefined);
stream_settings_ui.update_stream_description( stream_settings_ui.update_stream_description(
sub, sub,
value, value,
other_values.rendered_description, other_values.rendered_description,
); );
break; },
case "email_address": email_address(value) {
sub.email_address = value; sub.email_address = value;
break; },
case "pin_to_top": pin_to_top(value) {
update_stream_setting(sub, value, property); update_stream_setting(sub, value, "pin_to_top");
stream_list.refresh_pinned_or_unpinned_stream(sub); stream_list.refresh_pinned_or_unpinned_stream(sub);
break; },
case "invite_only": invite_only(value) {
assert(other_values !== undefined);
stream_settings_ui.update_stream_privacy(sub, { stream_settings_ui.update_stream_privacy(sub, {
invite_only: value, invite_only: value,
history_public_to_subscribers: other_values.history_public_to_subscribers, history_public_to_subscribers: other_values.history_public_to_subscribers,
is_web_public: other_values.is_web_public, is_web_public: other_values.is_web_public,
}); });
compose_recipient.on_compose_select_recipient_update(); compose_recipient.on_compose_select_recipient_update();
break; },
case "stream_post_policy": stream_post_policy(value) {
stream_settings_ui.update_stream_post_policy(sub, value); stream_settings_ui.update_stream_post_policy(sub, value);
break; },
case "message_retention_days": message_retention_days(value) {
stream_settings_ui.update_message_retention_setting(sub, value); stream_settings_ui.update_message_retention_setting(sub, value);
break; },
case "can_remove_subscribers_group": can_remove_subscribers_group(value) {
stream_settings_ui.update_can_remove_subscribers_group(sub, value); stream_settings_ui.update_can_remove_subscribers_group(sub, value);
break; },
default: };
if (Object.hasOwn(updaters, property) && updaters[property] !== undefined) {
updaters[property](value);
} else {
blueslip.warn("Unexpected subscription property type", { blueslip.warn("Unexpected subscription property type", {
property, property,
value, value,
@@ -117,7 +159,7 @@ export function update_property(stream_id, property, value, other_values) {
} }
} }
function show_first_stream_created_modal(stream) { function show_first_stream_created_modal(stream: StreamSubscription): void {
dialog_widget.launch({ dialog_widget.launch({
html_heading: $t_html( html_heading: $t_html(
{defaultMessage: "Channel <b><z-stream></z-stream></b> created!"}, {defaultMessage: "Channel <b><z-stream></z-stream></b> created!"},
@@ -127,7 +169,9 @@ function show_first_stream_created_modal(stream) {
), ),
html_body: render_first_stream_created_modal({stream}), html_body: render_first_stream_created_modal({stream}),
id: "first_stream_created_modal", id: "first_stream_created_modal",
on_click() {}, on_click(): void {
/* This modal is purely informational and doesn't do anything when closed. */
},
html_submit_button: $t({defaultMessage: "Continue"}), html_submit_button: $t({defaultMessage: "Continue"}),
close_on_submit: true, close_on_submit: true,
single_footer_button: true, single_footer_button: true,
@@ -137,7 +181,11 @@ function show_first_stream_created_modal(stream) {
// Add yourself to a stream we already know about client-side. // Add yourself to a stream we already know about client-side.
// It's likely we should be passing in the full sub object from the caller/backend, // It's likely we should be passing in the full sub object from the caller/backend,
// but for now we just pass in the subscribers and color (things likely to be different). // but for now we just pass in the subscribers and color (things likely to be different).
export function mark_subscribed(sub, subscribers, color) { export function mark_subscribed(
sub: StreamSubscription | undefined,
subscribers: number[],
color: string | undefined,
): void {
if (sub === undefined) { if (sub === undefined) {
blueslip.error("Undefined sub passed to mark_subscribed"); blueslip.error("Undefined sub passed to mark_subscribed");
return; return;
@@ -204,7 +252,7 @@ export function mark_subscribed(sub, subscribers, color) {
user_profile.update_user_profile_streams_list_for_users([people.my_current_user_id()]); user_profile.update_user_profile_streams_list_for_users([people.my_current_user_id()]);
} }
export function mark_unsubscribed(sub) { export function mark_unsubscribed(sub: StreamSubscription | undefined): void {
if (sub === undefined) { if (sub === undefined) {
// We don't know about this stream // We don't know about this stream
return; return;
@@ -242,7 +290,7 @@ export function mark_unsubscribed(sub) {
user_profile.update_user_profile_streams_list_for_users([people.my_current_user_id()]); user_profile.update_user_profile_streams_list_for_users([people.my_current_user_id()]);
} }
export function remove_deactivated_user_from_all_streams(user_id) { export function remove_deactivated_user_from_all_streams(user_id: number): void {
const all_subs = stream_data.get_unsorted_subs(); const all_subs = stream_data.get_unsorted_subs();
for (const sub of all_subs) { for (const sub of all_subs) {
@@ -253,13 +301,15 @@ export function remove_deactivated_user_from_all_streams(user_id) {
} }
} }
export function process_subscriber_update(user_ids, stream_ids) { export function process_subscriber_update(user_ids: number[], stream_ids: number[]): void {
for (const stream_id of stream_ids) { for (const stream_id of stream_ids) {
const sub = sub_store.get(stream_id); const sub = sub_store.get(stream_id);
assert(sub !== undefined);
stream_settings_ui.update_subscribers_ui(sub); stream_settings_ui.update_subscribers_ui(sub);
} }
user_profile.update_user_profile_streams_list_for_users(user_ids); user_profile.update_user_profile_streams_list_for_users(user_ids);
if (stream_ids.includes(narrow_state.stream_id())) { const narrow_stream_id = narrow_state.stream_id();
if (narrow_stream_id && stream_ids.includes(narrow_stream_id)) {
activity_ui.build_user_sidebar(); activity_ui.build_user_sidebar();
} }
} }

View File

@@ -24,7 +24,7 @@ import * as settings_realm_user_settings_defaults from "./settings_realm_user_se
import * as settings_streams from "./settings_streams.ts"; import * as settings_streams from "./settings_streams.ts";
import * as settings_users from "./settings_users.ts"; import * as settings_users from "./settings_users.ts";
import {current_user, realm} from "./state_data.ts"; import {current_user, realm} from "./state_data.ts";
import * as stream_events from "./stream_events.js"; import * as stream_events from "./stream_events.ts";
import * as user_group_edit from "./user_group_edit.js"; import * as user_group_edit from "./user_group_edit.js";
import * as user_profile from "./user_profile.ts"; import * as user_profile from "./user_profile.ts";

View File

@@ -33,6 +33,7 @@ mock_esm("../src/recent_view_ui", {
}); });
mock_esm("../src/settings_notifications", { mock_esm("../src/settings_notifications", {
update_page() {}, update_page() {},
user_settings_panel: "stub", // Not used, but can't be undefined
}); });
mock_esm("../src/overlays", { mock_esm("../src/overlays", {
streams_open: () => true, streams_open: () => true,
@@ -479,7 +480,18 @@ test("process_subscriber_update", ({override, override_rewire}) => {
const userIds = [104, 2, 3]; const userIds = [104, 2, 3];
// Sample stream IDs // Sample stream IDs
const streamIds = [1, 2, 3]; const streamIds = [1, 2, 3];
stream_data.add_sub({
stream_id: 1,
name: "Rome",
});
stream_data.add_sub({
stream_id: 2,
name: "Denmark",
});
stream_data.add_sub({
stream_id: 3,
name: "Paris",
});
// Call the function being tested // Call the function being tested
stream_events.process_subscriber_update(userIds, streamIds); stream_events.process_subscriber_update(userIds, streamIds);