2023-04-07 04:58:17 +02:00
|
|
|
/* Compose box module responsible for the message's recipient */
|
|
|
|
|
2023-03-31 06:27:36 +02:00
|
|
|
import $ from "jquery";
|
|
|
|
import _ from "lodash";
|
|
|
|
|
2023-04-15 03:35:23 +02:00
|
|
|
// todo: fix circular import here
|
|
|
|
import * as compose_actions from "./compose_actions";
|
2023-04-23 14:18:48 +02:00
|
|
|
import * as compose_banner from "./compose_banner";
|
2023-03-31 06:27:36 +02:00
|
|
|
import * as compose_fade from "./compose_fade";
|
|
|
|
import * as compose_state from "./compose_state";
|
|
|
|
import * as compose_validate from "./compose_validate";
|
|
|
|
import {DropdownListWidget} from "./dropdown_list_widget";
|
|
|
|
import {$t} from "./i18n";
|
|
|
|
import * as narrow_state from "./narrow_state";
|
|
|
|
import * as stream_bar from "./stream_bar";
|
|
|
|
import * as stream_data from "./stream_data";
|
|
|
|
import * as util from "./util";
|
|
|
|
|
2023-04-18 05:13:50 +02:00
|
|
|
export let compose_recipient_widget;
|
2023-03-31 06:27:36 +02:00
|
|
|
|
2023-04-15 03:35:23 +02:00
|
|
|
const DIRECT_MESSAGE = "direct";
|
|
|
|
|
2023-03-31 06:27:36 +02:00
|
|
|
function composing_to_current_topic_narrow() {
|
|
|
|
return (
|
|
|
|
util.lower_same(compose_state.stream_name(), narrow_state.stream() || "") &&
|
|
|
|
util.lower_same(compose_state.topic(), narrow_state.topic() || "")
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function composing_to_current_private_message_narrow() {
|
|
|
|
const compose_state_recipient = compose_state.private_message_recipient();
|
|
|
|
const narrow_state_recipient = narrow_state.pm_emails_string();
|
|
|
|
return (
|
|
|
|
compose_state_recipient &&
|
|
|
|
narrow_state_recipient &&
|
|
|
|
_.isEqual(
|
|
|
|
compose_state_recipient
|
|
|
|
.split(",")
|
|
|
|
.map((s) => s.trim())
|
|
|
|
.sort(),
|
|
|
|
narrow_state_recipient
|
|
|
|
.split(",")
|
|
|
|
.map((s) => s.trim())
|
|
|
|
.sort(),
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function update_narrow_to_recipient_visibility() {
|
|
|
|
const message_type = compose_state.get_message_type();
|
|
|
|
if (message_type === "stream") {
|
|
|
|
const stream_name = compose_state.stream_name();
|
|
|
|
const stream_exists = Boolean(stream_data.get_stream_id(stream_name));
|
|
|
|
|
|
|
|
if (
|
|
|
|
stream_exists &&
|
|
|
|
!composing_to_current_topic_narrow() &&
|
|
|
|
compose_state.has_full_recipient()
|
|
|
|
) {
|
|
|
|
$(".narrow_to_compose_recipients").toggleClass("invisible", false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (message_type === "private") {
|
|
|
|
const recipients = compose_state.private_message_recipient();
|
|
|
|
if (
|
|
|
|
recipients &&
|
|
|
|
!composing_to_current_private_message_narrow() &&
|
|
|
|
compose_state.has_full_recipient()
|
|
|
|
) {
|
|
|
|
$(".narrow_to_compose_recipients").toggleClass("invisible", false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$(".narrow_to_compose_recipients").toggleClass("invisible", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
function update_fade() {
|
|
|
|
if (!compose_state.composing()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const msg_type = compose_state.get_message_type();
|
|
|
|
|
|
|
|
// It's possible that the new topic is not a resolved topic
|
|
|
|
// so we clear the older warning.
|
|
|
|
compose_validate.clear_topic_resolved_warning();
|
|
|
|
|
|
|
|
compose_validate.warn_if_topic_resolved();
|
|
|
|
compose_fade.set_focused_recipient(msg_type);
|
|
|
|
compose_fade.update_all();
|
|
|
|
}
|
|
|
|
|
|
|
|
export function update_on_recipient_change() {
|
|
|
|
update_fade();
|
|
|
|
update_narrow_to_recipient_visibility();
|
|
|
|
}
|
|
|
|
|
|
|
|
export function open_compose_stream_dropup() {
|
2023-04-18 05:13:50 +02:00
|
|
|
if ($("#id_compose_select_recipient").hasClass("open")) {
|
2023-03-31 06:27:36 +02:00
|
|
|
return;
|
|
|
|
}
|
2023-04-21 05:19:45 +02:00
|
|
|
// We trigger a click rather than directly toggling the element;
|
|
|
|
// this is important to ensure the filter text gets cleared when
|
|
|
|
// reopening the widget after previous use.
|
2023-04-18 05:13:50 +02:00
|
|
|
$("#id_compose_select_recipient > .dropdown-toggle").trigger("click");
|
2023-03-31 06:27:36 +02:00
|
|
|
}
|
|
|
|
|
2023-04-23 14:18:48 +02:00
|
|
|
export function check_stream_posting_policy_for_compose_box(stream_name) {
|
|
|
|
const stream = stream_data.get_sub_by_name(stream_name);
|
|
|
|
if (!stream) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const can_post_messages_in_stream = stream_data.can_post_messages_in_stream(stream);
|
|
|
|
if (!can_post_messages_in_stream) {
|
|
|
|
$(".compose_right_float_container").addClass("disabled-compose-send-button-container");
|
|
|
|
compose_banner.show_error_message(
|
|
|
|
$t({
|
|
|
|
defaultMessage: "You do not have permission to post in this stream.",
|
|
|
|
}),
|
|
|
|
compose_banner.CLASSNAMES.no_post_permissions,
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
$(".compose_right_float_container").removeClass("disabled-compose-send-button-container");
|
|
|
|
compose_banner.clear_errors();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-15 03:35:23 +02:00
|
|
|
function switch_message_type(message_type) {
|
|
|
|
$("#compose-content .alert").hide();
|
|
|
|
|
|
|
|
compose_state.set_message_type(message_type);
|
|
|
|
|
|
|
|
const opts = {
|
|
|
|
message_type,
|
|
|
|
trigger: "toggle recipient type",
|
|
|
|
stream: compose_state.stream_name(),
|
|
|
|
topic: compose_state.topic(),
|
|
|
|
private_message_recipient: compose_state.private_message_recipient(),
|
|
|
|
};
|
|
|
|
compose_actions.show_compose_box(message_type, opts);
|
|
|
|
}
|
|
|
|
|
2023-04-18 05:13:50 +02:00
|
|
|
export function on_compose_select_recipient_update(new_value) {
|
2023-04-15 03:35:23 +02:00
|
|
|
const message_type = compose_state.get_message_type();
|
|
|
|
if (new_value === DIRECT_MESSAGE) {
|
|
|
|
// TODO: In theory, we could do something more lightweight in
|
|
|
|
// the case it's already that value, but doing nothing would
|
|
|
|
// display the wrong and fail to update focus properly.
|
|
|
|
switch_message_type("private");
|
|
|
|
|
|
|
|
if (compose_state.private_message_recipient().length === 0) {
|
|
|
|
$("#private_message_recipient").trigger("focus").trigger("select");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const $stream_header_colorblock = $("#compose_recipient_selection_dropdown").find(
|
|
|
|
".stream_header_colorblock",
|
|
|
|
);
|
|
|
|
stream_bar.decorate(new_value, $stream_header_colorblock);
|
|
|
|
if (message_type === "private") {
|
|
|
|
switch_message_type("stream");
|
|
|
|
}
|
|
|
|
// Always move focus to the topic input even if it's not empty,
|
|
|
|
// since it's likely the user will want to update the topic
|
|
|
|
// after updating the stream.
|
|
|
|
$("#stream_message_recipient_topic").trigger("focus").trigger("select");
|
|
|
|
check_stream_posting_policy_for_compose_box(new_value);
|
|
|
|
}
|
2023-03-31 06:27:36 +02:00
|
|
|
update_on_recipient_change();
|
|
|
|
}
|
|
|
|
|
|
|
|
export function update_stream_dropdown_options() {
|
2023-04-22 23:40:14 +02:00
|
|
|
compose_recipient_widget.replace_data(get_options_for_recipient_widget());
|
2023-03-31 06:27:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export function possibly_update_dropdown_selection(old_stream_name, new_stream_name) {
|
|
|
|
const selected_stream = compose_state.stream_name();
|
|
|
|
if (selected_stream === old_stream_name) {
|
|
|
|
compose_state.set_stream_name(new_stream_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-22 23:40:14 +02:00
|
|
|
function get_options_for_recipient_widget() {
|
2023-04-15 03:35:23 +02:00
|
|
|
const options = stream_data
|
2023-03-31 06:27:36 +02:00
|
|
|
.subscribed_subs()
|
|
|
|
.map((stream) => ({
|
|
|
|
name: stream.name,
|
|
|
|
value: stream.name,
|
|
|
|
stream,
|
|
|
|
}))
|
|
|
|
.sort((a, b) => {
|
|
|
|
if (a.name.toLowerCase() < b.name.toLowerCase()) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (a.name.toLowerCase() > b.name.toLowerCase()) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
});
|
2023-04-15 03:35:23 +02:00
|
|
|
|
|
|
|
const direct_messages_option = {
|
|
|
|
name: $t({defaultMessage: "Direct message"}),
|
|
|
|
value: DIRECT_MESSAGE,
|
|
|
|
};
|
|
|
|
options.unshift(direct_messages_option);
|
|
|
|
return options;
|
2023-04-22 23:40:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export function initialize() {
|
2023-03-31 06:27:36 +02:00
|
|
|
const opts = {
|
2023-04-18 05:13:50 +02:00
|
|
|
widget_name: "compose_select_recipient",
|
2023-04-22 23:40:14 +02:00
|
|
|
data: get_options_for_recipient_widget(),
|
2023-03-31 06:27:36 +02:00
|
|
|
default_text: $t({defaultMessage: "Select a stream"}),
|
|
|
|
value: null,
|
2023-04-18 05:13:50 +02:00
|
|
|
on_update: on_compose_select_recipient_update,
|
2023-03-31 06:27:36 +02:00
|
|
|
};
|
2023-04-18 05:13:50 +02:00
|
|
|
compose_recipient_widget = new DropdownListWidget(opts);
|
|
|
|
compose_recipient_widget.setup();
|
2023-03-31 06:27:36 +02:00
|
|
|
|
2023-04-18 05:13:50 +02:00
|
|
|
$("#compose_select_recipient_widget").on("select", (e) => {
|
2023-03-31 06:27:36 +02:00
|
|
|
// We often focus on input fields to bring the user to fill it out.
|
|
|
|
// In this situation, a focus on the dropdown div opens the dropdown
|
|
|
|
// menu so that the user can select an option.
|
|
|
|
open_compose_stream_dropup();
|
|
|
|
e.stopPropagation();
|
|
|
|
});
|
|
|
|
|
|
|
|
// `keyup` isn't relevant for streams since it registers as a change only
|
|
|
|
// when an item in the dropdown is selected.
|
|
|
|
$("#stream_message_recipient_topic,#private_message_recipient").on(
|
|
|
|
"keyup",
|
|
|
|
update_on_recipient_change,
|
|
|
|
);
|
2023-04-18 05:13:50 +02:00
|
|
|
// changes for the stream dropdown are handled in on_compose_select_recipient_update
|
2023-03-31 06:27:36 +02:00
|
|
|
$("#stream_message_recipient_topic,#private_message_recipient").on("change", () => {
|
|
|
|
update_on_recipient_change();
|
|
|
|
compose_state.set_recipient_edited_manually(true);
|
|
|
|
});
|
|
|
|
}
|