typing_status: Use TypeScript unions for 'Recipient' type.

Typing 'Recipient' as union of 'stream' and 'direct' message type will help with upcoming type inference.
This commit is contained in:
Varun Singh 2024-01-24 00:16:07 +05:30 committed by Tim Abbott
parent b64a9d6ae0
commit 391e2a8e01
4 changed files with 61 additions and 41 deletions

View File

@ -4,16 +4,23 @@
"use strict"; "use strict";
type RecipientUserIds<UserId: number> = $ReadOnlyArray<UserId>; type DirectMessageObject<UserId: number> = {|
type StreamTopicObject = {|stream_id: number, topic: string|}; message_type: string,
ids: $ReadOnlyArray<UserId>,
|};
type StreamObject = {|
message_type: string,
stream_id: number,
topic: string,
|};
type Worker<UserId> = {| type Worker<UserId> = {|
get_current_time: () => number, // as ms since epoch get_current_time: () => number, // as ms since epoch
notify_server_start: (RecipientUserIds<UserId> | StreamTopicObject) => void, notify_server_start: (DirectMessageObject<UserId> | StreamObject) => void,
notify_server_stop: (RecipientUserIds<UserId> | StreamTopicObject) => void, notify_server_stop: (DirectMessageObject<UserId> | StreamObject) => void,
|}; |};
declare export function update<UserId>( declare export function update<UserId>(
worker: Worker<UserId>, worker: Worker<UserId>,
new_recipient: RecipientUserIds<UserId> | StreamTopicObject | null, new_recipient: DirectMessageObject<UserId> | StreamObject | null,
): void; ): void;

View File

@ -5,7 +5,14 @@ type StreamTopic = {
stream_id: number; stream_id: number;
topic: string; topic: string;
}; };
type Recipient = number[] | StreamTopic; export type Recipient =
| {
message_type: "direct";
ids: number[];
}
| (StreamTopic & {
message_type: "stream";
});
type TypingStatusWorker = { type TypingStatusWorker = {
get_current_time: () => number; get_current_time: () => number;
notify_server_start: (recipient: Recipient) => void; notify_server_start: (recipient: Recipient) => void;
@ -32,10 +39,10 @@ function same_recipient(a: Recipient | null, b: Recipient | null): boolean {
return false; return false;
} }
if (Array.isArray(a) && Array.isArray(b)) { if (a.message_type === "direct" && b.message_type === "direct") {
// direct message recipients // direct message recipients
return _.isEqual(a, b); return _.isEqual(a.ids, b.ids);
} else if (!Array.isArray(a) && !Array.isArray(b)) { } else if (a.message_type === "stream" && b.message_type === "stream") {
// stream recipients // stream recipients
return same_stream_and_topic(a, b); 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 * @param {*} worker Callbacks for reaching the real world. See typing.js
* for implementations. * for implementations.
* @param {*} new_recipient Depends on type of message being composed. If * @param {*} new_recipient Depends on type of message being composed. If
* * Direct message: The users the DM being composed is addressed to, * * Direct message: An Object containing id of users the DM being composed is addressed to
* as a sorted array of user IDs * and a message_type="direct" property.
* * Stream message: An Object containing the stream_id and topic * * Stream message: An Object containing stream_id, topic and message_type="stream".
* * No message is being composed: `null` * * No message is being composed: `null`
*/ */
export function update( export function update(

View File

@ -48,10 +48,9 @@ function send_stream_typing_notification(stream_id, topic, operation) {
} }
function send_typing_notification_based_on_message_type(to, operation) { function send_typing_notification_based_on_message_type(to, operation) {
const message_type = to.stream_id ? "stream" : "direct"; if (to.message_type === "direct" && user_settings.send_private_typing_notifications) {
if (message_type === "direct" && user_settings.send_private_typing_notifications) { send_direct_message_typing_notification(to.ids, operation);
send_direct_message_typing_notification(to, operation); } else if (to.message_type === "stream" && user_settings.send_stream_typing_notifications) {
} else if (message_type === "stream" && user_settings.send_stream_typing_notifications) {
send_stream_typing_notification(to.stream_id, to.topic, operation); send_stream_typing_notification(to.stream_id, to.topic, operation);
} }
} }
@ -89,13 +88,20 @@ function notify_server_stop(to) {
export function get_recipient() { export function get_recipient() {
const message_type = compose_state.get_message_type(); const message_type = compose_state.get_message_type();
if (message_type === "private") { if (message_type === "private") {
return get_user_ids_array(); return {
message_type: "direct",
ids: get_user_ids_array(),
};
} }
if (message_type === "stream") { if (message_type === "stream") {
const stream_name = compose_state.stream_name(); const stream_name = compose_state.stream_name();
const stream_id = stream_data.get_stream_id(stream_name); const stream_id = stream_data.get_stream_id(stream_name);
const topic = compose_state.topic(); const topic = compose_state.topic();
return {stream_id, topic}; return {
message_type: "stream",
stream_id,
topic,
};
} }
return null; return null;
} }

View File

@ -50,12 +50,12 @@ run_test("basics", ({override, override_rewire}) => {
set_global("clearTimeout", clear_timeout); set_global("clearTimeout", clear_timeout);
function notify_server_start(recipient) { function notify_server_start(recipient) {
assert.deepStrictEqual(recipient, [1, 2]); assert.deepStrictEqual(recipient, {message_type: "direct", ids: [1, 2]});
events.started = true; events.started = true;
} }
function notify_server_stop(recipient) { function notify_server_stop(recipient) {
assert.deepStrictEqual(recipient, [1, 2]); assert.deepStrictEqual(recipient, {message_type: "direct", ids: [1, 2]});
events.stopped = true; events.stopped = true;
} }
@ -83,11 +83,11 @@ run_test("basics", ({override, override_rewire}) => {
}; };
// Start talking to users having ids - 1, 2. // 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, { assert.deepEqual(typing_status.state, {
next_send_start_time: make_time(5 + 10), next_send_start_time: make_time(5 + 10),
idle_timer: "idle_timer_stub", idle_timer: "idle_timer_stub",
current_recipient: [1, 2], current_recipient: {message_type: "direct", ids: [1, 2]},
}); });
assert.deepEqual(events, { assert.deepEqual(events, {
idle_callback: events.idle_callback, idle_callback: events.idle_callback,
@ -99,11 +99,11 @@ run_test("basics", ({override, override_rewire}) => {
// type again 3 seconds later // type again 3 seconds later
worker.get_current_time = returns_time(8); worker.get_current_time = returns_time(8);
call_handler([1, 2]); call_handler({message_type: "direct", ids: [1, 2]});
assert.deepEqual(typing_status.state, { assert.deepEqual(typing_status.state, {
next_send_start_time: make_time(5 + 10), next_send_start_time: make_time(5 + 10),
idle_timer: "idle_timer_stub", idle_timer: "idle_timer_stub",
current_recipient: [1, 2], current_recipient: {message_type: "direct", ids: [1, 2]},
}); });
assert.deepEqual(events, { assert.deepEqual(events, {
idle_callback: events.idle_callback, 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 // type after 15 secs, so that we can notify the server
// again // again
worker.get_current_time = returns_time(18); worker.get_current_time = returns_time(18);
call_handler([1, 2]); call_handler({message_type: "direct", ids: [1, 2]});
assert.deepEqual(typing_status.state, { assert.deepEqual(typing_status.state, {
next_send_start_time: make_time(18 + 10), next_send_start_time: make_time(18 + 10),
idle_timer: "idle_timer_stub", idle_timer: "idle_timer_stub",
current_recipient: [1, 2], current_recipient: {message_type: "direct", ids: [1, 2]},
}); });
assert.deepEqual(events, { assert.deepEqual(events, {
idle_callback: events.idle_callback, idle_callback: events.idle_callback,
@ -153,11 +153,11 @@ run_test("basics", ({override, override_rewire}) => {
// Start talking to users again. // Start talking to users again.
worker.get_current_time = returns_time(50); worker.get_current_time = returns_time(50);
call_handler([1, 2]); call_handler({message_type: "direct", ids: [1, 2]});
assert.deepEqual(typing_status.state, { assert.deepEqual(typing_status.state, {
next_send_start_time: make_time(50 + 10), next_send_start_time: make_time(50 + 10),
idle_timer: "idle_timer_stub", idle_timer: "idle_timer_stub",
current_recipient: [1, 2], current_recipient: {message_type: "direct", ids: [1, 2]},
}); });
assert.deepEqual(events, { assert.deepEqual(events, {
idle_callback: events.idle_callback, idle_callback: events.idle_callback,
@ -179,11 +179,11 @@ run_test("basics", ({override, override_rewire}) => {
// Start talking to users again. // Start talking to users again.
worker.get_current_time = returns_time(80); worker.get_current_time = returns_time(80);
call_handler([1, 2]); call_handler({message_type: "direct", ids: [1, 2]});
assert.deepEqual(typing_status.state, { assert.deepEqual(typing_status.state, {
next_send_start_time: make_time(80 + 10), next_send_start_time: make_time(80 + 10),
idle_timer: "idle_timer_stub", idle_timer: "idle_timer_stub",
current_recipient: [1, 2], current_recipient: {message_type: "direct", ids: [1, 2]},
}); });
assert.deepEqual(events, { assert.deepEqual(events, {
idle_callback: events.idle_callback, idle_callback: events.idle_callback,
@ -215,11 +215,11 @@ run_test("basics", ({override, override_rewire}) => {
// Start talking to users again. // Start talking to users again.
worker.get_current_time = returns_time(170); worker.get_current_time = returns_time(170);
call_handler([1, 2]); call_handler({message_type: "direct", ids: [1, 2]});
assert.deepEqual(typing_status.state, { assert.deepEqual(typing_status.state, {
next_send_start_time: make_time(170 + 10), next_send_start_time: make_time(170 + 10),
idle_timer: "idle_timer_stub", idle_timer: "idle_timer_stub",
current_recipient: [1, 2], current_recipient: {message_type: "direct", ids: [1, 2]},
}); });
assert.deepEqual(events, { assert.deepEqual(events, {
idle_callback: events.idle_callback, idle_callback: events.idle_callback,
@ -233,15 +233,15 @@ run_test("basics", ({override, override_rewire}) => {
worker.get_current_time = returns_time(171); worker.get_current_time = returns_time(171);
worker.notify_server_start = (recipient) => { worker.notify_server_start = (recipient) => {
assert.deepStrictEqual(recipient, [3, 4]); assert.deepStrictEqual(recipient, {message_type: "direct", ids: [3, 4]});
events.started = true; events.started = true;
}; };
call_handler([3, 4]); call_handler({message_type: "direct", ids: [3, 4]});
assert.deepEqual(typing_status.state, { assert.deepEqual(typing_status.state, {
next_send_start_time: make_time(171 + 10), next_send_start_time: make_time(171 + 10),
idle_timer: "idle_timer_stub", idle_timer: "idle_timer_stub",
current_recipient: [3, 4], current_recipient: {message_type: "direct", ids: [3, 4]},
}); });
assert.deepEqual(events, { assert.deepEqual(events, {
idle_callback: events.idle_callback, idle_callback: events.idle_callback,
@ -343,12 +343,12 @@ run_test("stream_messages", ({override_rewire}) => {
set_global("clearTimeout", clear_timeout); set_global("clearTimeout", clear_timeout);
function notify_server_start(recipient) { 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; events.started = true;
} }
function notify_server_stop(recipient) { 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; events.stopped = true;
} }
@ -376,11 +376,11 @@ run_test("stream_messages", ({override_rewire}) => {
}; };
// Start typing stream message // 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, { assert.deepEqual(typing_status.state, {
next_send_start_time: make_time(5 + 10), next_send_start_time: make_time(5 + 10),
idle_timer: "idle_timer_stub", 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, { assert.deepEqual(events, {
idle_callback: events.idle_callback, 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. // type again 3 seconds later. Covers 'same_stream_and_topic' codepath.
worker.get_current_time = returns_time(8); 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, { assert.deepEqual(typing_status.state, {
next_send_start_time: make_time(5 + 10), next_send_start_time: make_time(5 + 10),
idle_timer: "idle_timer_stub", 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, { assert.deepEqual(events, {
idle_callback: events.idle_callback, idle_callback: events.idle_callback,