diff --git a/tools/test-js-with-node b/tools/test-js-with-node
index 1848796b2b..00209fd366 100755
--- a/tools/test-js-with-node
+++ b/tools/test-js-with-node
@@ -226,6 +226,7 @@ EXEMPT_FILES = make_set(
"web/src/stream_muting.js",
"web/src/stream_popover.js",
"web/src/stream_settings_api.js",
+ "web/src/stream_settings_components.js",
"web/src/stream_settings_containers.ts",
"web/src/stream_settings_ui.js",
"web/src/stream_ui_updates.js",
diff --git a/web/src/compose_setup.js b/web/src/compose_setup.js
index 89a466c285..30986ba967 100644
--- a/web/src/compose_setup.js
+++ b/web/src/compose_setup.js
@@ -18,7 +18,7 @@ import * as rows from "./rows";
import * as scheduled_messages from "./scheduled_messages";
import * as scheduled_messages_popover from "./scheduled_messages_popover";
import * as stream_data from "./stream_data";
-import * as stream_settings_ui from "./stream_settings_ui";
+import * as stream_settings_components from "./stream_settings_components";
import * as sub_store from "./sub_store";
import * as subscriber_api from "./subscriber_api";
import {get_timestamp_for_flatpickr} from "./timerender";
@@ -134,7 +134,7 @@ export function initialize() {
return;
}
const sub = stream_data.get_sub_by_id(stream_id);
- stream_settings_ui.sub_or_unsub(sub);
+ stream_settings_components.sub_or_unsub(sub);
$(user_not_subscribed_selector).remove();
},
);
diff --git a/web/src/stream_create.js b/web/src/stream_create.js
index af349b6b05..a3af22fe84 100644
--- a/web/src/stream_create.js
+++ b/web/src/stream_create.js
@@ -14,7 +14,7 @@ import * as people from "./people";
import * as settings_data from "./settings_data";
import * as stream_create_subscribers from "./stream_create_subscribers";
import * as stream_data from "./stream_data";
-import * as stream_settings_ui from "./stream_settings_ui";
+import * as stream_settings_components from "./stream_settings_components";
import * as stream_ui_updates from "./stream_ui_updates";
import * as ui_report from "./ui_report";
import {parse_html} from "./ui_util";
@@ -259,7 +259,7 @@ function create_stream() {
data.principals = JSON.stringify(user_ids);
const can_remove_subscribers_group_id = Number.parseInt(
- stream_settings_ui.new_stream_can_remove_subscribers_group_widget.value(),
+ stream_settings_components.new_stream_can_remove_subscribers_group_widget.value(),
10,
);
data.can_remove_subscribers_group = can_remove_subscribers_group_id;
@@ -309,7 +309,7 @@ function create_stream() {
export function new_stream_clicked(stream_name) {
// this changes the tab switcher (settings/preview) which isn't necessary
// to a add new stream title.
- stream_settings_ui.show_subs_pane.create_stream();
+ stream_settings_components.show_subs_pane.create_stream();
$(".stream-row.active").removeClass("active");
if (stream_name !== "") {
@@ -328,7 +328,9 @@ function clear_error_display() {
export function show_new_stream_modal() {
$("#stream-creation").removeClass("hide");
$(".right .settings").hide();
- stream_settings_ui.hide_or_disable_stream_privacy_options_if_required($("#stream-creation"));
+ stream_settings_components.hide_or_disable_stream_privacy_options_if_required(
+ $("#stream-creation"),
+ );
stream_create_subscribers.build_widgets();
@@ -458,5 +460,5 @@ export function set_up_handlers() {
}
});
- stream_settings_ui.new_stream_can_remove_subscribers_group_widget.setup();
+ stream_settings_components.new_stream_can_remove_subscribers_group_widget.setup();
}
diff --git a/web/src/stream_edit.js b/web/src/stream_edit.js
index c511657742..88f36c5d6b 100644
--- a/web/src/stream_edit.js
+++ b/web/src/stream_edit.js
@@ -29,9 +29,9 @@ import * as stream_data from "./stream_data";
import * as stream_edit_subscribers from "./stream_edit_subscribers";
import * as stream_edit_toggler from "./stream_edit_toggler";
import * as stream_settings_api from "./stream_settings_api";
+import * as stream_settings_components from "./stream_settings_components";
import * as stream_settings_containers from "./stream_settings_containers";
import * as stream_settings_data from "./stream_settings_data";
-import * as stream_settings_ui from "./stream_settings_ui";
import * as stream_ui_updates from "./stream_ui_updates";
import * as sub_store from "./sub_store";
import * as ui_report from "./ui_report";
@@ -94,17 +94,17 @@ export function open_edit_panel_for_row(stream_row) {
const sub = get_sub_for_target(stream_row);
$(".stream-row.active").removeClass("active");
- stream_settings_ui.show_subs_pane.settings(sub);
+ stream_settings_components.show_subs_pane.settings(sub);
$(stream_row).addClass("active");
setup_subscriptions_stream_hash(sub);
setup_stream_settings(stream_row);
}
export function open_edit_panel_empty() {
- const tab_key = stream_settings_ui.get_active_data().$tabs.first().attr("data-tab-key");
+ const tab_key = stream_settings_components.get_active_data().$tabs.first().attr("data-tab-key");
$(".stream-row.active").removeClass("active");
$("#subscription_overlay .right").removeClass("show");
- stream_settings_ui.show_subs_pane.nothing_selected();
+ stream_settings_components.show_subs_pane.nothing_selected();
setup_subscriptions_tab_hash(tab_key);
}
@@ -113,9 +113,9 @@ export function update_stream_name(sub, new_name) {
$edit_container.find(".email-address").text(sub.email_address);
$edit_container.find(".sub-stream-name").text(new_name);
- const active_data = stream_settings_ui.get_active_data();
+ const active_data = stream_settings_components.get_active_data();
if (active_data.id === sub.stream_id) {
- stream_settings_ui.set_right_panel_title(sub);
+ stream_settings_components.set_right_panel_title(sub);
}
}
@@ -358,7 +358,7 @@ export function initialize() {
return;
}
- stream_settings_ui.sub_or_unsub(sub);
+ stream_settings_components.sub_or_unsub(sub);
});
$("#streams_overlay_container").on("click", "#open_stream_info_modal", (e) => {
@@ -425,7 +425,7 @@ export function initialize() {
)}']`,
);
const sub = sub_store.get(stream_id);
- stream_settings_ui.sub_or_unsub(sub, $stream_row);
+ stream_settings_components.sub_or_unsub(sub, $stream_row);
$("#stream_permission_settings .stream-permissions-warning-banner").empty();
},
);
@@ -542,7 +542,7 @@ export function initialize() {
sub.stream_id,
)}']`,
);
- stream_settings_ui.sub_or_unsub(sub, $stream_row);
+ stream_settings_components.sub_or_unsub(sub, $stream_row);
if (!sub.subscribed) {
open_edit_panel_for_row($stream_row);
diff --git a/web/src/stream_popover.js b/web/src/stream_popover.js
index 139d14baac..9cb70715e4 100644
--- a/web/src/stream_popover.js
+++ b/web/src/stream_popover.js
@@ -21,6 +21,7 @@ import * as stream_bar from "./stream_bar";
import * as stream_color from "./stream_color";
import * as stream_data from "./stream_data";
import * as stream_settings_api from "./stream_settings_api";
+import * as stream_settings_components from "./stream_settings_components";
import * as stream_settings_ui from "./stream_settings_ui";
import * as sub_store from "./sub_store";
import * as ui_report from "./ui_report";
@@ -177,7 +178,7 @@ function build_stream_popover(opts) {
$(this).closest(".popover").fadeOut(500).delay(500).remove();
const sub = stream_popover_sub(e);
- stream_settings_ui.sub_or_unsub(sub);
+ stream_settings_components.sub_or_unsub(sub);
e.preventDefault();
e.stopPropagation();
});
diff --git a/web/src/stream_settings_components.js b/web/src/stream_settings_components.js
new file mode 100644
index 0000000000..5f384eae2c
--- /dev/null
+++ b/web/src/stream_settings_components.js
@@ -0,0 +1,252 @@
+import $ from "jquery";
+
+import render_unsubscribe_private_stream_modal from "../templates/confirm_dialog/confirm_unsubscribe_private_stream.hbs";
+import render_inline_decorated_stream_name from "../templates/inline_decorated_stream_name.hbs";
+import render_selected_stream_title from "../templates/stream_settings/selected_stream_title.hbs";
+
+import * as channel from "./channel";
+import * as confirm_dialog from "./confirm_dialog";
+import * as dropdown_widget from "./dropdown_widget";
+import {$t, $t_html} from "./i18n";
+import * as loading from "./loading";
+import * as overlays from "./overlays";
+import {page_params} from "./page_params";
+import * as peer_data from "./peer_data";
+import * as people from "./people";
+import * as settings_config from "./settings_config";
+import * as settings_data from "./settings_data";
+import * as stream_ui_updates from "./stream_ui_updates";
+import * as ui_report from "./ui_report";
+import * as user_groups from "./user_groups";
+
+export function set_right_panel_title(sub) {
+ let title_icon_color = "#333333";
+ if (settings_data.using_dark_theme()) {
+ title_icon_color = "#dddeee";
+ }
+ $("#subscription_overlay .stream-info-title").html(
+ render_selected_stream_title({sub, title_icon_color}),
+ );
+}
+
+export const show_subs_pane = {
+ nothing_selected() {
+ $(".settings, #stream-creation").hide();
+ $(".nothing-selected").show();
+ $("#subscription_overlay .stream-info-title").text($t({defaultMessage: "Stream settings"}));
+ },
+ settings(sub) {
+ $(".settings, #stream-creation").hide();
+ $(".settings").show();
+ set_right_panel_title(sub);
+ },
+ create_stream() {
+ $(".nothing-selected, .settings, #stream-creation").hide();
+ $("#stream-creation").show();
+ $("#subscription_overlay .stream-info-title").text($t({defaultMessage: "Create stream"}));
+ },
+};
+
+export function get_active_data() {
+ const $active_row = $("div.stream-row.active");
+ const valid_active_id = Number.parseInt($active_row.attr("data-stream-id"), 10);
+ const $active_tabs = $(".subscriptions-container").find("div.ind-tab.selected");
+ return {
+ $row: $active_row,
+ id: valid_active_id,
+ $tabs: $active_tabs,
+ };
+}
+
+export let new_stream_can_remove_subscribers_group_widget = null;
+
+export function dropdown_setup() {
+ new_stream_can_remove_subscribers_group_widget = new dropdown_widget.DropdownWidget({
+ widget_name: "new_stream_can_remove_subscribers_group",
+ get_options: () =>
+ user_groups.get_realm_user_groups_for_dropdown_list_widget(
+ "can_remove_subscribers_group",
+ ),
+ item_click_callback(event, dropdown) {
+ dropdown.hide();
+ event.preventDefault();
+ event.stopPropagation();
+ new_stream_can_remove_subscribers_group_widget.render();
+ },
+ $events_container: $("#subscription_overlay"),
+ tippy_props: {
+ placement: "bottom-start",
+ },
+ on_mount_callback(dropdown) {
+ $(dropdown.popper).css("min-width", "300px");
+ },
+ default_text: $t({defaultMessage: "No user groups"}),
+ default_id: user_groups.get_user_group_from_name("role:administrators").id,
+ unique_id_type: dropdown_widget.DATA_TYPES.NUMBER,
+ });
+}
+
+/* For the given stream_row, remove the tick and replace by a spinner. */
+function display_subscribe_toggle_spinner(stream_row) {
+ /* Prevent sending multiple requests by removing the button class. */
+ $(stream_row).find(".check").removeClass("sub_unsub_button");
+
+ /* Hide the tick. */
+ const $tick = $(stream_row).find("svg");
+ $tick.addClass("hide");
+
+ /* Add a spinner to show the request is in process. */
+ const $spinner = $(stream_row).find(".sub_unsub_status").expectOne();
+ $spinner.show();
+ loading.make_indicator($spinner);
+}
+
+/* For the given stream_row, add the tick and delete the spinner. */
+function hide_subscribe_toggle_spinner(stream_row) {
+ /* Re-enable the button to handle requests. */
+ $(stream_row).find(".check").addClass("sub_unsub_button");
+
+ /* Show the tick. */
+ const $tick = $(stream_row).find("svg");
+ $tick.removeClass("hide");
+
+ /* Destroy the spinner. */
+ const $spinner = $(stream_row).find(".sub_unsub_status").expectOne();
+ loading.destroy_indicator($spinner);
+}
+
+export function ajaxSubscribe(stream, color, $stream_row) {
+ // Subscribe yourself to a single stream.
+ let true_stream_name;
+
+ if ($stream_row !== undefined) {
+ display_subscribe_toggle_spinner($stream_row);
+ }
+ return channel.post({
+ url: "/json/users/me/subscriptions",
+ data: {subscriptions: JSON.stringify([{name: stream, color}])},
+ success(_resp, _statusText, xhr) {
+ if (overlays.streams_open()) {
+ $("#create_stream_name").val("");
+ }
+
+ const res = xhr.responseJSON;
+ if (!$.isEmptyObject(res.already_subscribed)) {
+ // Display the canonical stream capitalization.
+ true_stream_name = res.already_subscribed[people.my_current_email()][0];
+ ui_report.success(
+ $t_html(
+ {defaultMessage: "Already subscribed to {stream}"},
+ {stream: true_stream_name},
+ ),
+ $(".stream_change_property_info"),
+ );
+ }
+ // The rest of the work is done via the subscribe event we will get
+
+ if ($stream_row !== undefined) {
+ hide_subscribe_toggle_spinner($stream_row);
+ }
+ },
+ error(xhr) {
+ if ($stream_row !== undefined) {
+ hide_subscribe_toggle_spinner($stream_row);
+ }
+ ui_report.error(
+ $t_html({defaultMessage: "Error adding subscription"}),
+ xhr,
+ $(".stream_change_property_info"),
+ );
+ },
+ });
+}
+
+function ajaxUnsubscribe(sub, $stream_row) {
+ // TODO: use stream_id when backend supports it
+ if ($stream_row !== undefined) {
+ display_subscribe_toggle_spinner($stream_row);
+ }
+ return channel.del({
+ url: "/json/users/me/subscriptions",
+ data: {subscriptions: JSON.stringify([sub.name])},
+ success() {
+ $(".stream_change_property_info").hide();
+ // The rest of the work is done via the unsubscribe event we will get
+
+ if ($stream_row !== undefined) {
+ hide_subscribe_toggle_spinner($stream_row);
+ }
+ },
+ error(xhr) {
+ if ($stream_row !== undefined) {
+ hide_subscribe_toggle_spinner($stream_row);
+ }
+ ui_report.error(
+ $t_html({defaultMessage: "Error removing subscription"}),
+ xhr,
+ $(".stream_change_property_info"),
+ );
+ },
+ });
+}
+
+export function unsubscribe_from_private_stream(sub) {
+ const invite_only = sub.invite_only;
+ const sub_count = peer_data.get_subscriber_count(sub.stream_id);
+ const stream_name_with_privacy_symbol_html = render_inline_decorated_stream_name({stream: sub});
+
+ const html_body = render_unsubscribe_private_stream_modal({
+ message: $t({
+ defaultMessage: "Once you leave this stream, you will not be able to rejoin.",
+ }),
+ display_stream_archive_warning: sub_count === 1 && invite_only,
+ });
+
+ function unsubscribe_from_stream() {
+ let $stream_row;
+ if (overlays.streams_open()) {
+ $stream_row = $(
+ "#streams_overlay_container div.stream-row[data-stream-id='" + sub.stream_id + "']",
+ );
+ }
+
+ ajaxUnsubscribe(sub, $stream_row);
+ }
+
+ confirm_dialog.launch({
+ html_heading: $t_html(
+ {defaultMessage: "Unsubscribe from "},
+ {"z-link": () => stream_name_with_privacy_symbol_html},
+ ),
+ html_body,
+ on_click: unsubscribe_from_stream,
+ });
+}
+
+export function sub_or_unsub(sub, $stream_row) {
+ if (sub.subscribed) {
+ // TODO: This next line should allow guests to access web-public streams.
+ if (sub.invite_only || page_params.is_guest) {
+ unsubscribe_from_private_stream(sub);
+ return;
+ }
+ ajaxUnsubscribe(sub, $stream_row);
+ } else {
+ ajaxSubscribe(sub.name, sub.color, $stream_row);
+ }
+}
+
+export function update_public_stream_privacy_option_state($container) {
+ const $public_stream_elem = $container.find(
+ `input[value='${CSS.escape(settings_config.stream_privacy_policy_values.public.code)}']`,
+ );
+ $public_stream_elem.prop("disabled", !settings_data.user_can_create_public_streams());
+}
+
+export function hide_or_disable_stream_privacy_options_if_required($container) {
+ stream_ui_updates.update_web_public_stream_privacy_option_state($container);
+
+ update_public_stream_privacy_option_state($container);
+
+ stream_ui_updates.update_private_stream_privacy_option_state($container);
+}
diff --git a/web/src/stream_settings_ui.js b/web/src/stream_settings_ui.js
index ba16ef83f6..d0811e595f 100644
--- a/web/src/stream_settings_ui.js
+++ b/web/src/stream_settings_ui.js
@@ -1,34 +1,25 @@
import $ from "jquery";
import _ from "lodash";
-import render_unsubscribe_private_stream_modal from "../templates/confirm_dialog/confirm_unsubscribe_private_stream.hbs";
-import render_inline_decorated_stream_name from "../templates/inline_decorated_stream_name.hbs";
import render_browse_streams_list from "../templates/stream_settings/browse_streams_list.hbs";
import render_browse_streams_list_item from "../templates/stream_settings/browse_streams_list_item.hbs";
-import render_selected_stream_title from "../templates/stream_settings/selected_stream_title.hbs";
import render_stream_settings from "../templates/stream_settings/stream_settings.hbs";
import render_stream_settings_overlay from "../templates/stream_settings/stream_settings_overlay.hbs";
import * as blueslip from "./blueslip";
import * as browser_history from "./browser_history";
-import * as channel from "./channel";
import * as components from "./components";
import * as compose_recipient from "./compose_recipient";
import * as compose_state from "./compose_state";
-import * as confirm_dialog from "./confirm_dialog";
-import * as dropdown_widget from "./dropdown_widget";
import * as hash_parser from "./hash_parser";
import * as hash_util from "./hash_util";
-import {$t, $t_html} from "./i18n";
+import {$t} from "./i18n";
import * as keydown_util from "./keydown_util";
-import * as loading from "./loading";
import * as message_lists from "./message_lists";
import * as message_live_update from "./message_live_update";
import * as message_view_header from "./message_view_header";
import * as overlays from "./overlays";
import {page_params} from "./page_params";
-import * as peer_data from "./peer_data";
-import * as people from "./people";
import * as scroll_util from "./scroll_util";
import * as search_util from "./search_util";
import * as settings_config from "./settings_config";
@@ -39,41 +30,12 @@ import * as stream_edit from "./stream_edit";
import * as stream_edit_subscribers from "./stream_edit_subscribers";
import * as stream_list from "./stream_list";
import * as stream_settings_api from "./stream_settings_api";
+import * as stream_settings_components from "./stream_settings_components";
import * as stream_settings_data from "./stream_settings_data";
import * as stream_ui_updates from "./stream_ui_updates";
import * as sub_store from "./sub_store";
-import * as ui_report from "./ui_report";
-import * as user_groups from "./user_groups";
import * as util from "./util";
-export function set_right_panel_title(sub) {
- let title_icon_color = "#333333";
- if (settings_data.using_dark_theme()) {
- title_icon_color = "#dddeee";
- }
- $("#subscription_overlay .stream-info-title").html(
- render_selected_stream_title({sub, title_icon_color}),
- );
-}
-
-export const show_subs_pane = {
- nothing_selected() {
- $(".settings, #stream-creation").hide();
- $(".nothing-selected").show();
- $("#subscription_overlay .stream-info-title").text($t({defaultMessage: "Stream settings"}));
- },
- settings(sub) {
- $(".settings, #stream-creation").hide();
- $(".settings").show();
- set_right_panel_title(sub);
- },
- create_stream() {
- $(".nothing-selected, .settings, #stream-creation").hide();
- $("#stream-creation").show();
- $("#subscription_overlay .stream-info-title").text($t({defaultMessage: "Create stream"}));
- },
-};
-
export function is_sub_already_present(sub) {
return stream_ui_updates.row_for_stream_id(sub.stream_id).length > 0;
}
@@ -115,17 +77,6 @@ function get_row_data($row) {
return undefined;
}
-export function get_active_data() {
- const $active_row = $("div.stream-row.active");
- const valid_active_id = Number.parseInt($active_row.attr("data-stream-id"), 10);
- const $active_tabs = $(".subscriptions-container").find("div.ind-tab.selected");
- return {
- $row: $active_row,
- id: valid_active_id,
- $tabs: $active_tabs,
- };
-}
-
function selectText(element) {
const sel = window.getSelection();
const range = document.createRange();
@@ -201,9 +152,9 @@ export function update_stream_privacy(slim_sub, values) {
stream_ui_updates.enable_or_disable_subscribers_tab(sub);
stream_list.redraw_stream_privacy(sub);
- const active_data = get_active_data();
+ const active_data = stream_settings_components.get_active_data();
if (active_data.id === sub.stream_id) {
- set_right_panel_title(sub);
+ stream_settings_components.set_right_panel_title(sub);
}
// Update navbar if needed
@@ -227,7 +178,7 @@ export function update_can_remove_subscribers_group_id(sub, new_value) {
}
export function update_is_default_stream() {
- const active_stream_id = get_active_data().id;
+ const active_stream_id = stream_settings_components.get_active_data().id;
if (active_stream_id) {
const sub = sub_store.get(active_stream_id);
stream_ui_updates.update_setting_element(sub, "is_default_stream");
@@ -565,34 +516,6 @@ export function switch_stream_sort(tab_name) {
redraw_left_panel();
}
-export let new_stream_can_remove_subscribers_group_widget = null;
-
-function dropdown_setup() {
- new_stream_can_remove_subscribers_group_widget = new dropdown_widget.DropdownWidget({
- widget_name: "new_stream_can_remove_subscribers_group",
- get_options: () =>
- user_groups.get_realm_user_groups_for_dropdown_list_widget(
- "can_remove_subscribers_group",
- ),
- item_click_callback(event, dropdown) {
- dropdown.hide();
- event.preventDefault();
- event.stopPropagation();
- new_stream_can_remove_subscribers_group_widget.render();
- },
- $events_container: $("#subscription_overlay"),
- tippy_props: {
- placement: "bottom-start",
- },
- on_mount_callback(dropdown) {
- $(dropdown.popper).css("min-width", "300px");
- },
- default_text: $t({defaultMessage: "No user groups"}),
- default_id: user_groups.get_user_group_from_name("role:administrators").id,
- unique_id_type: dropdown_widget.DATA_TYPES.NUMBER,
- });
-}
-
export function setup_page(callback) {
// We should strongly consider only setting up the page once,
// but I am writing these comments write before a big release,
@@ -705,7 +628,7 @@ export function setup_page(callback) {
render_left_panel_superset();
initialize_components();
- dropdown_setup();
+ stream_settings_components.dropdown_setup();
redraw_left_panel();
stream_create.set_up_handlers();
@@ -759,14 +682,14 @@ export function switch_to_stream_row(stream_id) {
const $stream_row = stream_ui_updates.row_for_stream_id(stream_id);
const $container = $(".streams-list");
- get_active_data().$row.removeClass("active");
+ stream_settings_components.get_active_data().$row.removeClass("active");
$stream_row.addClass("active");
scroll_util.scroll_element_into_container($stream_row, $container);
// It's dubious that we need this timeout any more.
setTimeout(() => {
- if (stream_id === get_active_data().id) {
+ if (stream_id === stream_settings_components.get_active_data().id) {
$stream_row.trigger("click");
}
}, 100);
@@ -836,7 +759,7 @@ export function launch(section) {
});
change_state(section);
});
- if (!get_active_data().id) {
+ if (!stream_settings_components.get_active_data().id) {
if (section === "new") {
$("#create_stream_name").trigger("focus");
} else {
@@ -846,7 +769,7 @@ export function launch(section) {
}
export function switch_rows(event) {
- const active_data = get_active_data();
+ const active_data = stream_settings_components.get_active_data();
let $switch_row;
if (hash_parser.is_create_new_stream_narrow()) {
// Prevent switching stream rows when creating a new stream
@@ -880,15 +803,15 @@ export function switch_rows(event) {
}
export function keyboard_sub() {
- const active_data = get_active_data();
+ const active_data = stream_settings_components.get_active_data();
const row_data = get_row_data(active_data.$row);
if (row_data) {
- sub_or_unsub(row_data.object);
+ stream_settings_components.sub_or_unsub(row_data.object);
}
}
export function toggle_view(event) {
- const active_data = get_active_data();
+ const active_data = stream_settings_components.get_active_data();
const stream_filter_tab = active_data.$tabs.first().text();
if (event === "right_arrow" && stream_filter_tab === "Subscribed") {
@@ -899,7 +822,7 @@ export function toggle_view(event) {
}
export function view_stream() {
- const active_data = get_active_data();
+ const active_data = stream_settings_components.get_active_data();
const row_data = get_row_data(active_data.$row);
if (row_data) {
const stream_narrow_hash =
@@ -908,110 +831,6 @@ export function view_stream() {
}
}
-/* For the given stream_row, remove the tick and replace by a spinner. */
-function display_subscribe_toggle_spinner(stream_row) {
- /* Prevent sending multiple requests by removing the button class. */
- $(stream_row).find(".check").removeClass("sub_unsub_button");
-
- /* Hide the tick. */
- const $tick = $(stream_row).find("svg");
- $tick.addClass("hide");
-
- /* Add a spinner to show the request is in process. */
- const $spinner = $(stream_row).find(".sub_unsub_status").expectOne();
- $spinner.show();
- loading.make_indicator($spinner);
-}
-
-/* For the given stream_row, add the tick and delete the spinner. */
-function hide_subscribe_toggle_spinner(stream_row) {
- /* Re-enable the button to handle requests. */
- $(stream_row).find(".check").addClass("sub_unsub_button");
-
- /* Show the tick. */
- const $tick = $(stream_row).find("svg");
- $tick.removeClass("hide");
-
- /* Destroy the spinner. */
- const $spinner = $(stream_row).find(".sub_unsub_status").expectOne();
- loading.destroy_indicator($spinner);
-}
-
-function ajaxSubscribe(stream, color, $stream_row) {
- // Subscribe yourself to a single stream.
- let true_stream_name;
-
- if ($stream_row !== undefined) {
- display_subscribe_toggle_spinner($stream_row);
- }
- return channel.post({
- url: "/json/users/me/subscriptions",
- data: {subscriptions: JSON.stringify([{name: stream, color}])},
- success(_resp, _statusText, xhr) {
- if (overlays.streams_open()) {
- $("#create_stream_name").val("");
- }
-
- const res = xhr.responseJSON;
- if (!$.isEmptyObject(res.already_subscribed)) {
- // Display the canonical stream capitalization.
- true_stream_name = res.already_subscribed[people.my_current_email()][0];
- ui_report.success(
- $t_html(
- {defaultMessage: "Already subscribed to {stream}"},
- {stream: true_stream_name},
- ),
- $(".stream_change_property_info"),
- );
- }
- // The rest of the work is done via the subscribe event we will get
-
- if ($stream_row !== undefined) {
- hide_subscribe_toggle_spinner($stream_row);
- }
- },
- error(xhr) {
- if ($stream_row !== undefined) {
- hide_subscribe_toggle_spinner($stream_row);
- }
- ui_report.error(
- $t_html({defaultMessage: "Error adding subscription"}),
- xhr,
- $(".stream_change_property_info"),
- );
- },
- });
-}
-
-function ajaxUnsubscribe(sub, $stream_row) {
- // TODO: use stream_id when backend supports it
- if ($stream_row !== undefined) {
- display_subscribe_toggle_spinner($stream_row);
- }
- return channel.del({
- url: "/json/users/me/subscriptions",
- data: {subscriptions: JSON.stringify([sub.name])},
- success() {
- $(".stream_change_property_info").hide();
- // The rest of the work is done via the unsubscribe event we will get
-
- if ($stream_row !== undefined) {
- hide_subscribe_toggle_spinner($stream_row);
- }
- },
- error(xhr) {
- if ($stream_row !== undefined) {
- hide_subscribe_toggle_spinner($stream_row);
- }
- ui_report.error(
- $t_html({defaultMessage: "Error removing subscription"}),
- xhr,
- $(".stream_change_property_info"),
- );
- },
- });
-}
-
export function do_open_create_stream() {
// Only call this directly for hash changes.
// Prefer open_create_stream().
@@ -1021,7 +840,7 @@ export function do_open_create_stream() {
if (!should_list_all_streams()) {
// Realms that don't allow listing streams should simply be subscribed to.
stream_create.set_name(stream);
- ajaxSubscribe($("#search_stream_name").val());
+ stream_settings_components.ajaxSubscribe($("#search_stream_name").val());
return;
}
@@ -1033,67 +852,6 @@ export function open_create_stream() {
browser_history.update("#streams/new");
}
-export function unsubscribe_from_private_stream(sub) {
- const invite_only = sub.invite_only;
- const sub_count = peer_data.get_subscriber_count(sub.stream_id);
- const stream_name_with_privacy_symbol_html = render_inline_decorated_stream_name({stream: sub});
-
- const html_body = render_unsubscribe_private_stream_modal({
- message: $t({
- defaultMessage: "Once you leave this stream, you will not be able to rejoin.",
- }),
- display_stream_archive_warning: sub_count === 1 && invite_only,
- });
-
- function unsubscribe_from_stream() {
- let $stream_row;
- if (overlays.streams_open()) {
- $stream_row = $(
- "#streams_overlay_container div.stream-row[data-stream-id='" + sub.stream_id + "']",
- );
- }
-
- ajaxUnsubscribe(sub, $stream_row);
- }
-
- confirm_dialog.launch({
- html_heading: $t_html(
- {defaultMessage: "Unsubscribe from "},
- {"z-link": () => stream_name_with_privacy_symbol_html},
- ),
- html_body,
- on_click: unsubscribe_from_stream,
- });
-}
-
-export function sub_or_unsub(sub, $stream_row) {
- if (sub.subscribed) {
- // TODO: This next line should allow guests to access web-public streams.
- if (sub.invite_only || page_params.is_guest) {
- unsubscribe_from_private_stream(sub);
- return;
- }
- ajaxUnsubscribe(sub, $stream_row);
- } else {
- ajaxSubscribe(sub.name, sub.color, $stream_row);
- }
-}
-
-export function update_public_stream_privacy_option_state($container) {
- const $public_stream_elem = $container.find(
- `input[value='${CSS.escape(settings_config.stream_privacy_policy_values.public.code)}']`,
- );
- $public_stream_elem.prop("disabled", !settings_data.user_can_create_public_streams());
-}
-
-export function hide_or_disable_stream_privacy_options_if_required($container) {
- stream_ui_updates.update_web_public_stream_privacy_option_state($container);
-
- update_public_stream_privacy_option_state($container);
-
- stream_ui_updates.update_private_stream_privacy_option_state($container);
-}
-
export function update_stream_privacy_choices(policy) {
if (!overlays.streams_open()) {
return;
@@ -1113,7 +871,7 @@ export function update_stream_privacy_choices(policy) {
stream_ui_updates.update_private_stream_privacy_option_state($container);
}
if (policy === "create_public_stream_policy") {
- update_public_stream_privacy_option_state($container);
+ stream_settings_components.update_public_stream_privacy_option_state($container);
}
if (policy === "create_web_public_stream_policy") {
stream_ui_updates.update_web_public_stream_privacy_option_state($container);