mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
modal: Add options for marking messages as read.
We have updated our read messages confirmation modal to now offer three options for marking messages as read: - Muted topic messages - Messages from topics I don't follow - All unread messages Additionally, the modal now displays the count of unread messages for the selected option. Fixes: #30025.
This commit is contained in:
committed by
Tim Abbott
parent
01ce268d64
commit
bbc842484f
@@ -46,7 +46,7 @@ function register_mark_all_read_handler(
|
||||
>,
|
||||
): void {
|
||||
const {instance} = event.data;
|
||||
unread_ops.confirm_mark_all_as_read();
|
||||
unread_ops.confirm_mark_messages_as_read();
|
||||
popover_menus.hide_current_popover_if_visible(instance);
|
||||
}
|
||||
|
||||
|
@@ -41,6 +41,10 @@ export function clear_old_unreads_missing(): void {
|
||||
old_unreads_missing = false;
|
||||
}
|
||||
|
||||
export function set_old_unreads_missing_for_tests(value: boolean): void {
|
||||
old_unreads_missing = value;
|
||||
}
|
||||
|
||||
export const unread_mentions_counter = new Set<number>();
|
||||
export const direct_message_with_mention_count = new Set();
|
||||
const unread_messages = new Set<number>();
|
||||
@@ -912,6 +916,7 @@ export type FullUnreadCountsData = {
|
||||
stream_unread_messages: number;
|
||||
followed_topic_unread_messages_count: number;
|
||||
followed_topic_unread_messages_with_mention_count: number;
|
||||
unfollowed_topic_unread_messages_count: number;
|
||||
muted_topic_unread_messages_count: number;
|
||||
stream_count: Map<number, StreamCountInfo>;
|
||||
streams_with_mentions: number[];
|
||||
@@ -939,6 +944,8 @@ export function get_counts(): FullUnreadCountsData {
|
||||
followed_topic_unread_messages_count: topic_res.followed_topic_unread_messages,
|
||||
followed_topic_unread_messages_with_mention_count:
|
||||
unread_topic_counter.get_followed_topic_unread_mentions(),
|
||||
unfollowed_topic_unread_messages_count:
|
||||
unread_messages.size - topic_res.followed_topic_unread_messages - pm_res.total_count,
|
||||
muted_topic_unread_messages_count:
|
||||
unread_messages.size - topic_res.stream_unread_messages - pm_res.total_count,
|
||||
stream_count: topic_res.stream_count,
|
||||
|
@@ -3,7 +3,7 @@ import _ from "lodash";
|
||||
import assert from "minimalistic-assert";
|
||||
import {z} from "zod";
|
||||
|
||||
import render_confirm_mark_all_as_read from "../templates/confirm_dialog/confirm_mark_all_as_read.hbs";
|
||||
import render_confirm_mark_messages_as_read from "../templates/confirm_dialog/confirm_mark_all_as_read.hbs";
|
||||
import render_confirm_mark_as_unread_from_here from "../templates/confirm_dialog/confirm_mark_as_unread_from_here.hbs";
|
||||
import render_inline_decorated_channel_name from "../templates/inline_decorated_channel_name.hbs";
|
||||
import render_skipped_marking_unread from "../templates/skipped_marking_unread.hbs";
|
||||
@@ -66,17 +66,37 @@ export function is_window_focused(): boolean {
|
||||
return window_focused;
|
||||
}
|
||||
|
||||
export function confirm_mark_all_as_read(): void {
|
||||
const html_body = render_confirm_mark_all_as_read();
|
||||
export function confirm_mark_messages_as_read(): void {
|
||||
const html_body = render_confirm_mark_messages_as_read();
|
||||
|
||||
const modal_id = confirm_dialog.launch({
|
||||
html_heading: $t_html({defaultMessage: "Mark all messages as read?"}),
|
||||
html_heading: $t_html({defaultMessage: "Choose messages to mark as read"}),
|
||||
html_body,
|
||||
on_click() {
|
||||
mark_all_as_read(modal_id);
|
||||
handle_mark_messages_as_read(modal_id);
|
||||
},
|
||||
loading_spinner: true,
|
||||
});
|
||||
|
||||
// When the user clicks on "Mark messages as read," the dialog box opens with a
|
||||
// dropdown that, by default, displays the count of unread messages in
|
||||
// topics that the user does not follow.
|
||||
const default_messages_count = unread.get_counts().unfollowed_topic_unread_messages_count;
|
||||
$("#message_count").text(get_message_count_text(default_messages_count));
|
||||
|
||||
// When the user selects another option from the dropdown, this section is executed.
|
||||
$("#mark_as_read_option").on("change", function () {
|
||||
const selected_option = $(this).val();
|
||||
let messages_count;
|
||||
if (selected_option === "muted_topics") {
|
||||
messages_count = unread.get_counts().muted_topic_unread_messages_count;
|
||||
} else if (selected_option === "topics_not_followed") {
|
||||
messages_count = unread.get_counts().unfollowed_topic_unread_messages_count;
|
||||
} else {
|
||||
messages_count = unread.get_unread_message_count();
|
||||
}
|
||||
$("#message_count").text(get_message_count_text(messages_count));
|
||||
});
|
||||
}
|
||||
|
||||
const update_flags_for_narrow_response_schema = z.object({
|
||||
@@ -129,6 +149,24 @@ function handle_skipped_unsubscribed_streams(
|
||||
}
|
||||
}
|
||||
|
||||
export function get_message_count_text(count: number): string {
|
||||
if (unread.old_unreads_missing) {
|
||||
return $t(
|
||||
{
|
||||
defaultMessage: "{count}+ messages will be marked as read.",
|
||||
},
|
||||
{count},
|
||||
);
|
||||
}
|
||||
return $t(
|
||||
{
|
||||
defaultMessage:
|
||||
"{count, plural, one {# message} other {# messages}} will be marked as read.",
|
||||
},
|
||||
{count},
|
||||
);
|
||||
}
|
||||
|
||||
function bulk_update_read_flags_for_narrow(
|
||||
narrow: NarrowTerm[],
|
||||
op: "add" | "remove",
|
||||
@@ -329,6 +367,28 @@ function bulk_update_read_flags_for_narrow(
|
||||
});
|
||||
}
|
||||
|
||||
function handle_mark_messages_as_read(modal_id: string): void {
|
||||
const selected_option = $("#mark_as_read_option").val();
|
||||
|
||||
switch (selected_option) {
|
||||
case "muted_topics": {
|
||||
mark_muted_topic_messages_as_read(modal_id);
|
||||
break;
|
||||
}
|
||||
case "topics_not_followed": {
|
||||
mark_unfollowed_topic_messages_as_read(modal_id);
|
||||
break;
|
||||
}
|
||||
case "all_messages": {
|
||||
mark_all_as_read(modal_id);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert(false, `Invalid mark_as_read_option: ${String(selected_option)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function process_newly_read_message(
|
||||
message: Message,
|
||||
options: {from?: "pointer" | "server"},
|
||||
@@ -838,6 +898,31 @@ export function mark_all_as_read(modal_id?: string): void {
|
||||
bulk_update_read_flags_for_narrow(all_unread_messages_narrow, "add", {}, modal_id);
|
||||
}
|
||||
|
||||
export function mark_muted_topic_messages_as_read(modal_id?: string): void {
|
||||
bulk_update_read_flags_for_narrow(
|
||||
[
|
||||
{operator: "is", operand: "unread", negated: false},
|
||||
{operator: "is", operand: "muted", negated: false},
|
||||
],
|
||||
"add",
|
||||
{},
|
||||
modal_id,
|
||||
);
|
||||
}
|
||||
|
||||
export function mark_unfollowed_topic_messages_as_read(modal_id?: string): void {
|
||||
bulk_update_read_flags_for_narrow(
|
||||
[
|
||||
{operator: "is", operand: "unread", negated: false},
|
||||
{operator: "is", operand: "followed", negated: true},
|
||||
{operator: "is", operand: "dm", negated: true},
|
||||
],
|
||||
"add",
|
||||
{},
|
||||
modal_id,
|
||||
);
|
||||
}
|
||||
|
||||
export function mark_pm_as_read(user_ids_string: string): void {
|
||||
// user_ids_string is a stringified list of user ids which are
|
||||
// participants in the conversation other than the current
|
||||
|
@@ -367,6 +367,10 @@ select.settings_select {
|
||||
& label.checkbox + label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.message_count {
|
||||
margin: 10px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Class for displaying an input with an
|
||||
|
@@ -1,3 +1,11 @@
|
||||
<p>
|
||||
{{t "Are you sure you want to mark all messages as read? This action cannot be undone." }}
|
||||
{{t "Which messages do you want to mark as read? This action cannot be undone." }}
|
||||
</p>
|
||||
<div class="input-group">
|
||||
<select id="mark_as_read_option" class="modal_select bootstrap-style-font">
|
||||
<option value="muted_topics">{{t "Muted topics" }}</option>
|
||||
<option value="topics_not_followed" selected>{{t "Topics you don't follow" }}</option>
|
||||
<option value="all_messages">{{t "All messages" }}</option>
|
||||
</select>
|
||||
<p id="message_count" class="message_count"></p>
|
||||
</div>
|
||||
|
@@ -5,7 +5,7 @@
|
||||
<li role="none" class="link-item popover-menu-list-item">
|
||||
<a role="menuitem" id="mark_all_messages_as_read" class="popover-menu-link" tabindex="0">
|
||||
<i class="popover-menu-icon zulip-icon zulip-icon-mark-as-read" aria-hidden="true"></i>
|
||||
<span class="popover-menu-label">{{t "Mark all messages as read" }}</span>
|
||||
<span class="popover-menu-label">{{t "Mark messages as read" }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
<li role="none" class="link-item popover-menu-list-item">
|
||||
<a role="menuitem" id="mark_all_messages_as_read" class="popover-menu-link" tabindex="0">
|
||||
<i class="popover-menu-icon zulip-icon zulip-icon-mark-as-read" aria-hidden="true"></i>
|
||||
<span class="popover-menu-label">{{t "Mark all messages as read" }}</span>
|
||||
<span class="popover-menu-label">{{t "Mark messages as read" }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
<li role="none" class="link-item popover-menu-list-item">
|
||||
<a role="menuitem" id="mark_all_messages_as_read" class="popover-menu-link" tabindex="0">
|
||||
<i class="popover-menu-icon zulip-icon zulip-icon-mark-as-read" aria-hidden="true"></i>
|
||||
<span class="popover-menu-label">{{t "Mark all messages as read" }}</span>
|
||||
<span class="popover-menu-label">{{t "Mark messages as read" }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
|
32
web/tests/unread_ops.test.cjs
Normal file
32
web/tests/unread_ops.test.cjs
Normal file
@@ -0,0 +1,32 @@
|
||||
"use strict";
|
||||
|
||||
const assert = require("node:assert/strict");
|
||||
|
||||
const {set_global, zrequire} = require("./lib/namespace.cjs");
|
||||
const {run_test} = require("./lib/test.cjs");
|
||||
|
||||
set_global("document", {hasFocus: () => true});
|
||||
const unread = zrequire("unread");
|
||||
const unread_ops = zrequire("unread_ops");
|
||||
|
||||
run_test("get_message_count_text", () => {
|
||||
unread.set_old_unreads_missing_for_tests(true);
|
||||
assert.equal(
|
||||
unread_ops.get_message_count_text(5),
|
||||
"translated: 5+ messages will be marked as read.",
|
||||
);
|
||||
assert.equal(
|
||||
unread_ops.get_message_count_text(1),
|
||||
"translated: 1+ messages will be marked as read.",
|
||||
);
|
||||
|
||||
unread.set_old_unreads_missing_for_tests(false);
|
||||
assert.equal(
|
||||
unread_ops.get_message_count_text(5),
|
||||
"translated: 5 messages will be marked as read.",
|
||||
);
|
||||
assert.equal(
|
||||
unread_ops.get_message_count_text(1),
|
||||
"translated: 1 message will be marked as read.",
|
||||
);
|
||||
});
|
Reference in New Issue
Block a user