From 391e2a8e01d7f7dcd77438dc33b4d6e46a807311 Mon Sep 17 00:00:00 2001 From: Varun Singh Date: Wed, 24 Jan 2024 00:16:07 +0530 Subject: [PATCH] typing_status: Use TypeScript unions for 'Recipient' type. Typing 'Recipient' as union of 'stream' and 'direct' message type will help with upcoming type inference. --- web/shared/src/typing_status.js.flow | 17 +++++++--- web/shared/src/typing_status.ts | 21 ++++++++----- web/src/typing.js | 18 +++++++---- web/tests/typing_status.test.js | 46 ++++++++++++++-------------- 4 files changed, 61 insertions(+), 41 deletions(-) diff --git a/web/shared/src/typing_status.js.flow b/web/shared/src/typing_status.js.flow index 792362d4cd..df77841ef0 100644 --- a/web/shared/src/typing_status.js.flow +++ b/web/shared/src/typing_status.js.flow @@ -4,16 +4,23 @@ "use strict"; -type RecipientUserIds = $ReadOnlyArray; -type StreamTopicObject = {|stream_id: number, topic: string|}; +type DirectMessageObject = {| + message_type: string, + ids: $ReadOnlyArray, +|}; +type StreamObject = {| + message_type: string, + stream_id: number, + topic: string, +|}; type Worker = {| get_current_time: () => number, // as ms since epoch - notify_server_start: (RecipientUserIds | StreamTopicObject) => void, - notify_server_stop: (RecipientUserIds | StreamTopicObject) => void, + notify_server_start: (DirectMessageObject | StreamObject) => void, + notify_server_stop: (DirectMessageObject | StreamObject) => void, |}; declare export function update( worker: Worker, - new_recipient: RecipientUserIds | StreamTopicObject | null, + new_recipient: DirectMessageObject | StreamObject | null, ): void; diff --git a/web/shared/src/typing_status.ts b/web/shared/src/typing_status.ts index dc1a50419c..219af9be1e 100644 --- a/web/shared/src/typing_status.ts +++ b/web/shared/src/typing_status.ts @@ -5,7 +5,14 @@ type StreamTopic = { stream_id: number; topic: string; }; -type Recipient = number[] | StreamTopic; +export type Recipient = + | { + message_type: "direct"; + ids: number[]; + } + | (StreamTopic & { + message_type: "stream"; + }); type TypingStatusWorker = { get_current_time: () => number; notify_server_start: (recipient: Recipient) => void; @@ -32,10 +39,10 @@ function same_recipient(a: Recipient | null, b: Recipient | null): boolean { return false; } - if (Array.isArray(a) && Array.isArray(b)) { + if (a.message_type === "direct" && b.message_type === "direct") { // direct message recipients - return _.isEqual(a, b); - } else if (!Array.isArray(a) && !Array.isArray(b)) { + return _.isEqual(a.ids, b.ids); + } else if (a.message_type === "stream" && b.message_type === "stream") { // stream recipients return same_stream_and_topic(a, b); } @@ -120,9 +127,9 @@ export function maybe_ping_server( * @param {*} worker Callbacks for reaching the real world. See typing.js * for implementations. * @param {*} new_recipient Depends on type of message being composed. If - * * Direct message: The users the DM being composed is addressed to, - * as a sorted array of user IDs - * * Stream message: An Object containing the stream_id and topic + * * Direct message: An Object containing id of users the DM being composed is addressed to + * and a message_type="direct" property. + * * Stream message: An Object containing stream_id, topic and message_type="stream". * * No message is being composed: `null` */ export function update( diff --git a/web/src/typing.js b/web/src/typing.js index e5dd2a6022..518836c944 100644 --- a/web/src/typing.js +++ b/web/src/typing.js @@ -48,10 +48,9 @@ function send_stream_typing_notification(stream_id, topic, operation) { } function send_typing_notification_based_on_message_type(to, operation) { - const message_type = to.stream_id ? "stream" : "direct"; - if (message_type === "direct" && user_settings.send_private_typing_notifications) { - send_direct_message_typing_notification(to, operation); - } else if (message_type === "stream" && user_settings.send_stream_typing_notifications) { + if (to.message_type === "direct" && user_settings.send_private_typing_notifications) { + send_direct_message_typing_notification(to.ids, operation); + } else if (to.message_type === "stream" && user_settings.send_stream_typing_notifications) { send_stream_typing_notification(to.stream_id, to.topic, operation); } } @@ -89,13 +88,20 @@ function notify_server_stop(to) { export function get_recipient() { const message_type = compose_state.get_message_type(); if (message_type === "private") { - return get_user_ids_array(); + return { + message_type: "direct", + ids: get_user_ids_array(), + }; } if (message_type === "stream") { const stream_name = compose_state.stream_name(); const stream_id = stream_data.get_stream_id(stream_name); const topic = compose_state.topic(); - return {stream_id, topic}; + return { + message_type: "stream", + stream_id, + topic, + }; } return null; } diff --git a/web/tests/typing_status.test.js b/web/tests/typing_status.test.js index 0bd2bf051b..1d7685591d 100644 --- a/web/tests/typing_status.test.js +++ b/web/tests/typing_status.test.js @@ -50,12 +50,12 @@ run_test("basics", ({override, override_rewire}) => { set_global("clearTimeout", clear_timeout); function notify_server_start(recipient) { - assert.deepStrictEqual(recipient, [1, 2]); + assert.deepStrictEqual(recipient, {message_type: "direct", ids: [1, 2]}); events.started = true; } function notify_server_stop(recipient) { - assert.deepStrictEqual(recipient, [1, 2]); + assert.deepStrictEqual(recipient, {message_type: "direct", ids: [1, 2]}); events.stopped = true; } @@ -83,11 +83,11 @@ run_test("basics", ({override, override_rewire}) => { }; // Start talking to users having ids - 1, 2. - call_handler([1, 2]); + call_handler({message_type: "direct", ids: [1, 2]}); assert.deepEqual(typing_status.state, { next_send_start_time: make_time(5 + 10), idle_timer: "idle_timer_stub", - current_recipient: [1, 2], + current_recipient: {message_type: "direct", ids: [1, 2]}, }); assert.deepEqual(events, { idle_callback: events.idle_callback, @@ -99,11 +99,11 @@ run_test("basics", ({override, override_rewire}) => { // type again 3 seconds later worker.get_current_time = returns_time(8); - call_handler([1, 2]); + call_handler({message_type: "direct", ids: [1, 2]}); assert.deepEqual(typing_status.state, { next_send_start_time: make_time(5 + 10), idle_timer: "idle_timer_stub", - current_recipient: [1, 2], + current_recipient: {message_type: "direct", ids: [1, 2]}, }); assert.deepEqual(events, { idle_callback: events.idle_callback, @@ -116,11 +116,11 @@ run_test("basics", ({override, override_rewire}) => { // type after 15 secs, so that we can notify the server // again worker.get_current_time = returns_time(18); - call_handler([1, 2]); + call_handler({message_type: "direct", ids: [1, 2]}); assert.deepEqual(typing_status.state, { next_send_start_time: make_time(18 + 10), idle_timer: "idle_timer_stub", - current_recipient: [1, 2], + current_recipient: {message_type: "direct", ids: [1, 2]}, }); assert.deepEqual(events, { idle_callback: events.idle_callback, @@ -153,11 +153,11 @@ run_test("basics", ({override, override_rewire}) => { // Start talking to users again. worker.get_current_time = returns_time(50); - call_handler([1, 2]); + call_handler({message_type: "direct", ids: [1, 2]}); assert.deepEqual(typing_status.state, { next_send_start_time: make_time(50 + 10), idle_timer: "idle_timer_stub", - current_recipient: [1, 2], + current_recipient: {message_type: "direct", ids: [1, 2]}, }); assert.deepEqual(events, { idle_callback: events.idle_callback, @@ -179,11 +179,11 @@ run_test("basics", ({override, override_rewire}) => { // Start talking to users again. worker.get_current_time = returns_time(80); - call_handler([1, 2]); + call_handler({message_type: "direct", ids: [1, 2]}); assert.deepEqual(typing_status.state, { next_send_start_time: make_time(80 + 10), idle_timer: "idle_timer_stub", - current_recipient: [1, 2], + current_recipient: {message_type: "direct", ids: [1, 2]}, }); assert.deepEqual(events, { idle_callback: events.idle_callback, @@ -215,11 +215,11 @@ run_test("basics", ({override, override_rewire}) => { // Start talking to users again. worker.get_current_time = returns_time(170); - call_handler([1, 2]); + call_handler({message_type: "direct", ids: [1, 2]}); assert.deepEqual(typing_status.state, { next_send_start_time: make_time(170 + 10), idle_timer: "idle_timer_stub", - current_recipient: [1, 2], + current_recipient: {message_type: "direct", ids: [1, 2]}, }); assert.deepEqual(events, { idle_callback: events.idle_callback, @@ -233,15 +233,15 @@ run_test("basics", ({override, override_rewire}) => { worker.get_current_time = returns_time(171); worker.notify_server_start = (recipient) => { - assert.deepStrictEqual(recipient, [3, 4]); + assert.deepStrictEqual(recipient, {message_type: "direct", ids: [3, 4]}); events.started = true; }; - call_handler([3, 4]); + call_handler({message_type: "direct", ids: [3, 4]}); assert.deepEqual(typing_status.state, { next_send_start_time: make_time(171 + 10), idle_timer: "idle_timer_stub", - current_recipient: [3, 4], + current_recipient: {message_type: "direct", ids: [3, 4]}, }); assert.deepEqual(events, { idle_callback: events.idle_callback, @@ -343,12 +343,12 @@ run_test("stream_messages", ({override_rewire}) => { set_global("clearTimeout", clear_timeout); function notify_server_start(recipient) { - assert.deepStrictEqual(recipient, {stream_id: 3, topic: "test"}); + assert.deepStrictEqual(recipient, {message_type: "stream", stream_id: 3, topic: "test"}); events.started = true; } function notify_server_stop(recipient) { - assert.deepStrictEqual(recipient, {stream_id: 3, topic: "test"}); + assert.deepStrictEqual(recipient, {message_type: "stream", stream_id: 3, topic: "test"}); events.stopped = true; } @@ -376,11 +376,11 @@ run_test("stream_messages", ({override_rewire}) => { }; // Start typing stream message - call_handler({stream_id: 3, topic: "test"}); + call_handler({message_type: "stream", stream_id: 3, topic: "test"}); assert.deepEqual(typing_status.state, { next_send_start_time: make_time(5 + 10), idle_timer: "idle_timer_stub", - current_recipient: {stream_id: 3, topic: "test"}, + current_recipient: {message_type: "stream", stream_id: 3, topic: "test"}, }); assert.deepEqual(events, { idle_callback: events.idle_callback, @@ -392,11 +392,11 @@ run_test("stream_messages", ({override_rewire}) => { // type again 3 seconds later. Covers 'same_stream_and_topic' codepath. worker.get_current_time = returns_time(8); - call_handler({stream_id: 3, topic: "test"}); + call_handler({message_type: "stream", stream_id: 3, topic: "test"}); assert.deepEqual(typing_status.state, { next_send_start_time: make_time(5 + 10), idle_timer: "idle_timer_stub", - current_recipient: {stream_id: 3, topic: "test"}, + current_recipient: {message_type: "stream", stream_id: 3, topic: "test"}, }); assert.deepEqual(events, { idle_callback: events.idle_callback,