scheduled_messages: Indicate scheduled messages in conversation views.

These changes adds a new scheduled message indicator in conversation views
which informs the user of the number of messages that are scheduled to be
sent to the current view.

Fixes: #25584.
This commit is contained in:
Joelute 2023-09-26 13:33:53 -04:00 committed by Tim Abbott
parent 533ff863a7
commit 2cbf65b1f2
8 changed files with 104 additions and 0 deletions

View File

@ -259,6 +259,8 @@
<div class="message-list" id="zfilt" role="list" aria-live="polite" aria-label="{{ _('Messages') }}"> <div class="message-list" id="zfilt" role="list" aria-live="polite" aria-label="{{ _('Messages') }}">
</div> </div>
</div> </div>
<div id="scheduled_message_indicator">
</div>
<div id="typing_notifications"> <div id="typing_notifications">
</div> </div>
<div id="mark_read_on_scroll_state_banner"> <div id="mark_read_on_scroll_state_banner">

View File

@ -178,6 +178,7 @@ EXEMPT_FILES = make_set(
"web/src/resize_handler.js", "web/src/resize_handler.js",
"web/src/rows.js", "web/src/rows.js",
"web/src/scheduled_messages.js", "web/src/scheduled_messages.js",
"web/src/scheduled_messages_feed_ui.js",
"web/src/scheduled_messages_overlay_ui.js", "web/src/scheduled_messages_overlay_ui.js",
"web/src/scheduled_messages_popover.js", "web/src/scheduled_messages_popover.js",
"web/src/scheduled_messages_ui.js", "web/src/scheduled_messages_ui.js",

View File

@ -39,6 +39,7 @@ import * as pm_list from "./pm_list";
import * as recent_view_ui from "./recent_view_ui"; import * as recent_view_ui from "./recent_view_ui";
import * as recent_view_util from "./recent_view_util"; import * as recent_view_util from "./recent_view_util";
import * as resize from "./resize"; import * as resize from "./resize";
import * as scheduled_messages_feed_ui from "./scheduled_messages_feed_ui";
import * as search from "./search"; import * as search from "./search";
import {web_mark_read_on_scroll_policy_values} from "./settings_config"; import {web_mark_read_on_scroll_policy_values} from "./settings_config";
import * as spectators from "./spectators"; import * as spectators from "./spectators";
@ -922,6 +923,7 @@ export function to_compose_target() {
function handle_post_view_change(msg_list) { function handle_post_view_change(msg_list) {
const filter = msg_list.data.filter; const filter = msg_list.data.filter;
scheduled_messages_feed_ui.update_schedule_message_indicator();
typing_events.render_notifications_for_narrow(); typing_events.render_notifications_for_narrow();
if (filter.contains_only_private_messages()) { if (filter.contains_only_private_messages()) {

View File

@ -0,0 +1,64 @@
import $ from "jquery";
import render_scheduled_messages_indicator from "../templates/scheduled_messages_indicator.hbs";
import * as narrow_state from "./narrow_state";
import * as scheduled_messages from "./scheduled_messages";
import * as util from "./util";
function get_scheduled_messages_matching_narrow() {
const scheduled_messages_list = Object.values(scheduled_messages.scheduled_messages_data);
const filter = narrow_state.filter();
const is_conversation_view = filter === undefined ? false : filter.is_conversation_view();
const current_view_type = narrow_state.narrowed_to_pms() ? "private" : "stream";
if (!is_conversation_view) {
return false;
}
const matching_scheduled_messages = scheduled_messages_list.filter((scheduled_message) => {
// One could imagine excluding scheduled messages that failed
// to send, but structurally, we want to raise awareness of
// them -- we expect users to cancel/clear/reschedule those if
// aware of them.
if (current_view_type !== scheduled_message.type) {
return false;
}
if (scheduled_message.type === "private") {
// Both of these will be the user IDs for all participants including the
// current user sorted in ascending order.
if (scheduled_message.to.toString() === narrow_state.pm_ids_string()) {
return true;
}
} else if (scheduled_message.type === "stream") {
const narrow_dict = {
stream_id: narrow_state.stream_sub().stream_id,
topic: narrow_state.topic(),
};
const scheduled_message_dict = {
stream_id: scheduled_message.to,
topic: scheduled_message.topic,
};
if (util.same_stream_and_topic(narrow_dict, scheduled_message_dict)) {
return true;
}
}
return false;
});
return matching_scheduled_messages;
}
export function update_schedule_message_indicator() {
$("#scheduled_message_indicator").empty();
const matching_scheduled_messages = get_scheduled_messages_matching_narrow();
const scheduled_message_count = matching_scheduled_messages.length;
if (scheduled_message_count > 0) {
$("#scheduled_message_indicator").html(
render_scheduled_messages_indicator({
scheduled_message_count,
}),
);
}
}

View File

@ -43,6 +43,7 @@ import * as realm_playground from "./realm_playground";
import {realm_user_settings_defaults} from "./realm_user_settings_defaults"; import {realm_user_settings_defaults} from "./realm_user_settings_defaults";
import * as reload from "./reload"; import * as reload from "./reload";
import * as scheduled_messages from "./scheduled_messages"; import * as scheduled_messages from "./scheduled_messages";
import * as scheduled_messages_feed_ui from "./scheduled_messages_feed_ui";
import * as scheduled_messages_overlay_ui from "./scheduled_messages_overlay_ui"; import * as scheduled_messages_overlay_ui from "./scheduled_messages_overlay_ui";
import * as scheduled_messages_ui from "./scheduled_messages_ui"; import * as scheduled_messages_ui from "./scheduled_messages_ui";
import * as scroll_bar from "./scroll_bar"; import * as scroll_bar from "./scroll_bar";
@ -493,12 +494,14 @@ export function dispatch_normal_event(event) {
switch (event.op) { switch (event.op) {
case "add": { case "add": {
scheduled_messages.add_scheduled_messages(event.scheduled_messages); scheduled_messages.add_scheduled_messages(event.scheduled_messages);
scheduled_messages_feed_ui.update_schedule_message_indicator();
scheduled_messages_overlay_ui.rerender(); scheduled_messages_overlay_ui.rerender();
left_sidebar_navigation_area.update_scheduled_messages_row(); left_sidebar_navigation_area.update_scheduled_messages_row();
break; break;
} }
case "remove": { case "remove": {
scheduled_messages.remove_scheduled_message(event.scheduled_message_id); scheduled_messages.remove_scheduled_message(event.scheduled_message_id);
scheduled_messages_feed_ui.update_schedule_message_indicator();
scheduled_messages_ui.hide_scheduled_message_success_compose_banner( scheduled_messages_ui.hide_scheduled_message_success_compose_banner(
event.scheduled_message_id, event.scheduled_message_id,
); );

View File

@ -18,3 +18,23 @@
} }
} }
} }
#scheduled_message_indicator {
display: block;
margin-left: 10px;
font-style: italic;
color: hsl(0deg 0% 53%);
}
@media (width < $xl_min) {
#scheduled_message_indicator {
margin-right: 7px;
}
}
@media (width < $md_min) {
#scheduled_message_indicator {
margin-right: 7px;
margin-left: 7px;
}
}

View File

@ -0,0 +1,7 @@
<div class="scheduled_message_indicator">
{{#tr}}
You have <z-link>{scheduled_message_count, plural, =1 {1 scheduled message} other {# scheduled messages}}</z-link> for this conversation.
{{#*inline "z-link"}}<a href='/#scheduled'>{{> @partial-block}}</a>{{/inline}}
{{/tr}}
</div>

View File

@ -43,7 +43,9 @@ const realm_logo = mock_esm("../src/realm_logo");
const realm_playground = mock_esm("../src/realm_playground"); const realm_playground = mock_esm("../src/realm_playground");
const reload = mock_esm("../src/reload"); const reload = mock_esm("../src/reload");
const scheduled_messages = mock_esm("../src/scheduled_messages"); const scheduled_messages = mock_esm("../src/scheduled_messages");
const scheduled_messages_feed_ui = mock_esm("../src/scheduled_messages_feed_ui");
const scheduled_messages_overlay_ui = mock_esm("../src/scheduled_messages_overlay_ui"); const scheduled_messages_overlay_ui = mock_esm("../src/scheduled_messages_overlay_ui");
const scheduled_messages_ui = mock_esm("../src/scheduled_messages_ui");
const scroll_bar = mock_esm("../src/scroll_bar"); const scroll_bar = mock_esm("../src/scroll_bar");
const settings_account = mock_esm("../src/settings_account"); const settings_account = mock_esm("../src/settings_account");
const settings_bots = mock_esm("../src/settings_bots"); const settings_bots = mock_esm("../src/settings_bots");
@ -383,6 +385,9 @@ run_test("reaction", ({override}) => {
run_test("scheduled_messages", ({override}) => { run_test("scheduled_messages", ({override}) => {
override(scheduled_messages_overlay_ui, "rerender", noop); override(scheduled_messages_overlay_ui, "rerender", noop);
override(scheduled_messages_overlay_ui, "remove_scheduled_message_id", noop); override(scheduled_messages_overlay_ui, "remove_scheduled_message_id", noop);
override(scheduled_messages_feed_ui, "update_schedule_message_indicator", noop);
override(scheduled_messages_ui, "hide_scheduled_message_success_compose_banner", noop);
let event = event_fixtures.scheduled_messages__add; let event = event_fixtures.scheduled_messages__add;
{ {
const stub = make_stub(); const stub = make_stub();