From 84ffb471a2f1aaa25e8daccf5f97d5cb4cfff29a Mon Sep 17 00:00:00 2001 From: whilstsomebody Date: Tue, 29 Oct 2024 13:42:22 +0530 Subject: [PATCH] modal: Implement logic for marking various messages as read. This commit implements the logic for marking messages as read based on the selected option from the dropdown menu. Below the dropdown, count of the messages to be marked as read is displayed. The count value is updated dynamically as the selection in the dropdown is changed. Fixes part of #30025. --- .../left_sidebar_navigation_area_popovers.ts | 2 +- web/src/unread.ts | 6 ++ web/src/unread_ops.ts | 81 +++++++++++++++++-- web/styles/settings.css | 4 + .../confirm_mark_all_as_read.hbs | 2 +- 5 files changed, 87 insertions(+), 8 deletions(-) diff --git a/web/src/left_sidebar_navigation_area_popovers.ts b/web/src/left_sidebar_navigation_area_popovers.ts index 995dbd0738..acae1a7924 100644 --- a/web/src/left_sidebar_navigation_area_popovers.ts +++ b/web/src/left_sidebar_navigation_area_popovers.ts @@ -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); } diff --git a/web/src/unread.ts b/web/src/unread.ts index aebbdd1c61..c437e4744b 100644 --- a/web/src/unread.ts +++ b/web/src/unread.ts @@ -893,6 +893,8 @@ 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; streams_with_mentions: number[]; streams_with_unmuted_mentions: number[]; @@ -919,6 +921,10 @@ 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, streams_with_mentions: [...unread_topic_counter.get_streams_with_unread_mentions()], streams_with_unmuted_mentions: [ diff --git a/web/src/unread_ops.ts b/web/src/unread_ops.ts index 4886256a1a..7daeb7d686 100644 --- a/web/src/unread_ops.ts +++ b/web/src/unread_ops.ts @@ -3,14 +3,14 @@ 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 * as blueslip from "./blueslip.ts"; import * as channel from "./channel.ts"; import * as confirm_dialog from "./confirm_dialog.ts"; import * as desktop_notifications from "./desktop_notifications.ts"; import * as dialog_widget from "./dialog_widget.ts"; -import {$t_html} from "./i18n.ts"; +import {$t, $t_html} from "./i18n.ts"; import * as loading from "./loading.ts"; import * as message_flags from "./message_flags.ts"; import * as message_lists from "./message_lists.ts"; @@ -48,17 +48,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: "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(update_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 = default_messages_count; + } else { + messages_count = unread.get_unread_message_count(); + } + $("#message_count").text(update_message_count_text(messages_count)); + }); } const update_flags_for_narrow_response_schema = z.object({ @@ -70,6 +90,16 @@ const update_flags_for_narrow_response_schema = z.object({ found_newest: z.boolean(), }); +function update_message_count_text(count: number): string { + 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", @@ -240,6 +270,18 @@ 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(); + + if (selected_option === "muted_topics") { + mark_muted_topic_messages_as_read(modal_id); + } else if (selected_option === "topics_not_followed") { + mark_unfollowed_topic_messages_as_read(modal_id); + } else { + mark_all_as_read(modal_id); + } +} + function process_newly_read_message( message: Message, options: {from?: "pointer" | "server"}, @@ -618,7 +660,7 @@ export function mark_stream_as_read(stream_id: number): void { ); } -export function mark_topic_as_read(stream_id: number, topic: string): void { +export function mark_topic_as_read(stream_id: number, topic: string, modal_id?: string): void { bulk_update_read_flags_for_narrow( [ {operator: "is", operand: "unread", negated: false}, @@ -626,6 +668,8 @@ export function mark_topic_as_read(stream_id: number, topic: string): void { {operator: "topic", operand: topic}, ], "add", + {}, + modal_id, ); } @@ -643,6 +687,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: "in", operand: "home", negated: true}, + ], + "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 diff --git a/web/styles/settings.css b/web/styles/settings.css index 277ae2009b..e7adbc2888 100644 --- a/web/styles/settings.css +++ b/web/styles/settings.css @@ -354,6 +354,10 @@ select.settings_select { & label.checkbox + label { cursor: pointer; } + + .message_count { + margin: 5px 0 0; + } } /* Class for displaying an input with an diff --git a/web/templates/confirm_dialog/confirm_mark_all_as_read.hbs b/web/templates/confirm_dialog/confirm_mark_all_as_read.hbs index e1b88b82aa..600cffc722 100644 --- a/web/templates/confirm_dialog/confirm_mark_all_as_read.hbs +++ b/web/templates/confirm_dialog/confirm_mark_all_as_read.hbs @@ -7,5 +7,5 @@ -

+