From f0a88d51cc82fb362eeaad1e329cf91663863108 Mon Sep 17 00:00:00 2001 From: Kislay Verma Date: Thu, 7 Aug 2025 19:43:40 +0530 Subject: [PATCH] message_reminders: Add support for notes. This commit adds the ability for users to include notes with their message reminders. Fixes #35070. Co-Authored-By: Aman Agrawal --- api_docs/changelog.md | 8 +++ version.py | 2 +- web/src/compose_send_menu_popover.js | 27 ++++++--- web/src/hotkey.js | 11 ++++ web/src/message_reminder.ts | 3 +- web/src/scheduled_messages.ts | 3 + web/src/state_data.ts | 1 + web/styles/scheduled_messages.css | 8 +++ .../popovers/schedule_message_popover.hbs | 10 +++- web/tests/scheduled_messages.test.cjs | 5 ++ zerver/actions/reminders.py | 4 +- zerver/actions/scheduled_messages.py | 5 +- zerver/lib/events.py | 1 + zerver/lib/message.py | 1 + zerver/lib/reminders.py | 55 +++++++++++++++---- ...749_scheduledmessage_reminder_note_text.py | 17 ++++++ zerver/models/scheduled_jobs.py | 1 + zerver/openapi/zulip.yaml | 13 +++++ zerver/tests/test_home.py | 1 + zerver/tests/test_reminders.py | 51 ++++++++++++++++- zerver/views/reminders.py | 2 + zproject/default_settings.py | 5 ++ 22 files changed, 209 insertions(+), 25 deletions(-) create mode 100644 zerver/migrations/0749_scheduledmessage_reminder_note_text.py diff --git a/api_docs/changelog.md b/api_docs/changelog.md index 30b36d8451..26c1c23340 100644 --- a/api_docs/changelog.md +++ b/api_docs/changelog.md @@ -20,6 +20,14 @@ format used by the Zulip server that they are interacting with. ## Changes in Zulip 11.0 +**Feature level 415** + +* [`POST /reminders`](/api/create-message-reminder): Added parameter + `note` to allow users to add notes to their reminders. +* [`POST /register`](/api/register-queue): Added `max_reminder_note_length` + for clients to restrict the reminder note length before sending it to + the server. + **Feature level 414** * [`POST /channel_folders/create`](/api/create-channel-folder), diff --git a/version.py b/version.py index 26cb160a07..78f0b72a35 100644 --- a/version.py +++ b/version.py @@ -34,7 +34,7 @@ DESKTOP_WARNING_VERSION = "5.9.3" # new level means in api_docs/changelog.md, as well as "**Changes**" # entries in the endpoint's documentation in `zulip.yaml`. -API_FEATURE_LEVEL = 414 +API_FEATURE_LEVEL = 415 # Bump the minor PROVISION_VERSION to indicate that folks should provision # only when going from an old version of the code to a newer version. Bump diff --git a/web/src/compose_send_menu_popover.js b/web/src/compose_send_menu_popover.js index 1de5dde0fd..0fdd8a1067 100644 --- a/web/src/compose_send_menu_popover.js +++ b/web/src/compose_send_menu_popover.js @@ -35,13 +35,6 @@ export function open_schedule_message_menu( return; } let interval; - const message_schedule_callback = (time) => { - if (remind_message_id !== undefined) { - do_schedule_reminder(time, remind_message_id); - } else { - do_schedule_message(time); - } - }; popover_menus.toggle_popover_menu(target, { theme: "popover-menu", @@ -77,7 +70,23 @@ export function open_schedule_message_menu( ); }, onMount(instance) { + if (remind_message_id !== undefined) { + popover_menus.focus_first_popover_item( + popover_menus.get_popover_items_for_instance(instance), + ); + } const $popper = $(instance.popper); + const message_schedule_callback = (time) => { + if (remind_message_id !== undefined) { + do_schedule_reminder( + time, + remind_message_id, + $popper.find(".schedule-reminder-note").val(), + ); + } else { + do_schedule_message(time); + } + }; $popper.on("click", ".send_later_custom", (e) => { const $send_later_options_content = $popper.find(".popover-menu-list"); const current_time = new Date(); @@ -149,9 +158,9 @@ export function do_schedule_message(send_at_time) { compose.finish(true); } -export function do_schedule_reminder(send_at_time, remind_message_id) { +export function do_schedule_reminder(send_at_time, remind_message_id, note_text) { send_at_time = parse_sent_at_time(send_at_time); - message_reminder.set_message_reminder(send_at_time, remind_message_id); + message_reminder.set_message_reminder(send_at_time, remind_message_id, note_text); } function get_send_later_menu_items() { diff --git a/web/src/hotkey.js b/web/src/hotkey.js index fd5ab95059..58a6cdee90 100644 --- a/web/src/hotkey.js +++ b/web/src/hotkey.js @@ -523,6 +523,17 @@ function handle_popover_events(event_name) { } if (popover_menu_visible_instance) { + if ( + // Allow all hotkeys except for `down_arrow` and `up_arrow` + // to be handled by the browser. + // Added to handle `schedule-reminder-note` textarea. + processing_text() && + event_name !== "down_arrow" && + event_name !== "up_arrow" + ) { + return false; + } + popover_menus.sidebar_menu_instance_handle_keyboard( popover_menu_visible_instance, event_name, diff --git a/web/src/message_reminder.ts b/web/src/message_reminder.ts index f02d10c037..1fef6e4968 100644 --- a/web/src/message_reminder.ts +++ b/web/src/message_reminder.ts @@ -12,12 +12,13 @@ export type Reminder = z.infer; export const reminders_by_id = new Map(); -export function set_message_reminder(send_at_time: number, message_id: number): void { +export function set_message_reminder(send_at_time: number, message_id: number, note: string): void { channel.post({ url: "/json/reminders", data: { message_id, scheduled_delivery_timestamp: send_at_time, + note, }, success(): void { const populate: (element: JQuery) => void = ($container) => { diff --git a/web/src/scheduled_messages.ts b/web/src/scheduled_messages.ts index 393b4be43f..038ff57c67 100644 --- a/web/src/scheduled_messages.ts +++ b/web/src/scheduled_messages.ts @@ -3,6 +3,7 @@ import type * as z from "zod/mini"; import * as channel from "./channel.ts"; import {$t} from "./i18n.ts"; import type {StateData, scheduled_message_schema} from "./state_data.ts"; +import {realm} from "./state_data.ts"; import * as timerender from "./timerender.ts"; export type ScheduledMessage = z.infer; @@ -91,6 +92,7 @@ export function get_filtered_send_opts(date: Date): { send_later_tomorrow: SendOption; possible_send_later_monday: SendOption | false; send_later_custom: {text: string}; + max_reminder_note_length: number; } { const send_times = compute_send_times(date); @@ -195,6 +197,7 @@ export function get_filtered_send_opts(date: Date): { send_later_tomorrow, possible_send_later_monday, send_later_custom, + max_reminder_note_length: realm.max_reminder_note_length, }; } diff --git a/web/src/state_data.ts b/web/src/state_data.ts index 2c8ae7f736..18d070eb8e 100644 --- a/web/src/state_data.ts +++ b/web/src/state_data.ts @@ -300,6 +300,7 @@ export const realm_schema = z.object({ max_icon_file_size_mib: z.number(), max_logo_file_size_mib: z.number(), max_message_length: z.number(), + max_reminder_note_length: z.number(), max_stream_description_length: z.number(), max_stream_name_length: z.number(), max_topic_length: z.number(), diff --git a/web/styles/scheduled_messages.css b/web/styles/scheduled_messages.css index ade446ba91..6dd635ccdf 100644 --- a/web/styles/scheduled_messages.css +++ b/web/styles/scheduled_messages.css @@ -19,3 +19,11 @@ #reminders-overlay-container .message_content { cursor: auto; } + +.schedule-reminder-note { + /* Horizontal resizing in the popover doesn't look good at all. */ + resize: vertical; + width: 100%; + min-width: 10em; + padding: 3px; +} diff --git a/web/templates/popovers/schedule_message_popover.hbs b/web/templates/popovers/schedule_message_popover.hbs index cfb42ee528..ddd9c85ce9 100644 --- a/web/templates/popovers/schedule_message_popover.hbs +++ b/web/templates/popovers/schedule_message_popover.hbs @@ -1,4 +1,4 @@ -
+