mirror of https://github.com/zulip/zulip.git
message_store: Migrate message_store to typescript.
This commit is contained in:
parent
5dc1d36f73
commit
24dc2e783d
|
@ -119,7 +119,12 @@ js_rules = RuleList(
|
|||
rules=[
|
||||
{
|
||||
"pattern": "subject|SUBJECT",
|
||||
"exclude": {"web/src/types.ts", "web/src/util.ts", "web/tests/"},
|
||||
"exclude": {
|
||||
"web/src/message_store.ts",
|
||||
"web/src/types.ts",
|
||||
"web/src/util.ts",
|
||||
"web/tests/",
|
||||
},
|
||||
"exclude_pattern": "emails",
|
||||
"description": "avoid subject in JS code",
|
||||
"good_lines": ["topic_name"],
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import _ from "lodash";
|
||||
|
||||
import type {Message} from "./message_store";
|
||||
import * as people from "./people";
|
||||
import type {Message} from "./types";
|
||||
|
||||
// For simplicity, we use a list for our internal
|
||||
// data, since that matches what the server sends us.
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import assert from "minimalistic-assert";
|
||||
|
||||
import type {Message} from "./message_store";
|
||||
import * as stream_data from "./stream_data";
|
||||
import * as sub_store from "./sub_store";
|
||||
import type {Message} from "./types";
|
||||
import type {Recipient} from "./util";
|
||||
import * as util from "./util";
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as message_feed_loading from "./message_feed_loading";
|
||||
import type {RawMessage} from "./types";
|
||||
import type {RawMessage} from "./message_store";
|
||||
|
||||
function max_id_for_messages(messages: RawMessage[]): number {
|
||||
let max_id = 0;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import * as internal_url from "../shared/src/internal_url";
|
||||
|
||||
import type {Message} from "./message_store";
|
||||
import * as people from "./people";
|
||||
import * as stream_data from "./stream_data";
|
||||
import * as sub_store from "./sub_store";
|
||||
import type {StreamSubscription} from "./sub_store";
|
||||
import type {Message} from "./types";
|
||||
import type {UserGroup} from "./user_groups";
|
||||
|
||||
type Operator = {operator: string; operand: string; negated?: boolean};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import _ from "lodash";
|
||||
|
||||
import type {Message} from "./message_store";
|
||||
import * as people from "./people";
|
||||
import type {Message} from "./types";
|
||||
|
||||
const huddle_timestamps = new Map<string, number>();
|
||||
|
||||
|
|
|
@ -66,23 +66,23 @@ export function update_starred_view(message_id, new_value) {
|
|||
}
|
||||
|
||||
export function update_stream_name(stream_id, new_name) {
|
||||
message_store.update_property("stream_name", new_name, {stream_id});
|
||||
message_store.update_stream_name(stream_id, new_name);
|
||||
rerender_messages_view();
|
||||
}
|
||||
|
||||
export function update_user_full_name(user_id, full_name) {
|
||||
message_store.update_property("sender_full_name", full_name, {user_id});
|
||||
message_store.update_sender_full_name(user_id, full_name);
|
||||
rerender_messages_view_for_user(user_id);
|
||||
}
|
||||
|
||||
export function update_avatar(user_id, avatar_url) {
|
||||
let url = avatar_url;
|
||||
url = people.format_small_avatar_url(url);
|
||||
message_store.update_property("small_avatar_url", url, {user_id});
|
||||
message_store.update_small_avatar_url(user_id, url);
|
||||
rerender_messages_view_for_user(user_id);
|
||||
}
|
||||
|
||||
export function update_user_status_emoji(user_id, status_emoji_info) {
|
||||
message_store.update_property("status_emoji_info", status_emoji_info, {user_id});
|
||||
message_store.update_status_emoji_info(user_id, status_emoji_info);
|
||||
rerender_messages_view_for_user(user_id);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
// We only use jquery for parsing.
|
||||
import $ from "jquery";
|
||||
|
||||
// TODO: Move this to message_store when it is
|
||||
// converted to TypeScript.
|
||||
type Message = {
|
||||
content: string;
|
||||
};
|
||||
import type {Message} from "./message_store";
|
||||
|
||||
// We need to check if the message content contains the specified HTML
|
||||
// elements. We wrap the message.content in a <div>; this is
|
||||
|
|
|
@ -1,137 +0,0 @@
|
|||
import * as blueslip from "./blueslip";
|
||||
import * as people from "./people";
|
||||
|
||||
const stored_messages = new Map();
|
||||
|
||||
export function update_message_cache(message) {
|
||||
// You should only call this from message_helper (or in tests).
|
||||
stored_messages.set(message.id, message);
|
||||
}
|
||||
|
||||
export function get_cached_message(message_id) {
|
||||
// You should only call this from message_helper.
|
||||
// Use the get() wrapper below for most other use cases.
|
||||
return stored_messages.get(message_id);
|
||||
}
|
||||
|
||||
export function clear_for_testing() {
|
||||
stored_messages.clear();
|
||||
}
|
||||
|
||||
export function get(message_id) {
|
||||
if (message_id === undefined || message_id === null) {
|
||||
blueslip.error("message_store.get got bad value", {message_id});
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (typeof message_id !== "number") {
|
||||
blueslip.error("message_store got non-number", {message_id});
|
||||
|
||||
// Try to soldier on, assuming the caller treats message
|
||||
// ids as strings.
|
||||
message_id = Number.parseFloat(message_id);
|
||||
}
|
||||
|
||||
return stored_messages.get(message_id);
|
||||
}
|
||||
|
||||
export function get_pm_emails(message) {
|
||||
const user_ids = people.pm_with_user_ids(message);
|
||||
const emails = user_ids
|
||||
.map((user_id) => {
|
||||
const person = people.maybe_get_user_by_id(user_id);
|
||||
if (!person) {
|
||||
blueslip.error("Unknown user id", {user_id});
|
||||
return "?";
|
||||
}
|
||||
return person.email;
|
||||
})
|
||||
.sort();
|
||||
|
||||
return emails.join(", ");
|
||||
}
|
||||
|
||||
export function get_pm_full_names(message) {
|
||||
const user_ids = people.pm_with_user_ids(message);
|
||||
const names = people.get_display_full_names(user_ids).sort();
|
||||
|
||||
return names.join(", ");
|
||||
}
|
||||
|
||||
export function set_message_booleans(message) {
|
||||
const flags = message.flags || [];
|
||||
|
||||
function convert_flag(flag_name) {
|
||||
return flags.includes(flag_name);
|
||||
}
|
||||
|
||||
message.unread = !convert_flag("read");
|
||||
message.historical = convert_flag("historical");
|
||||
message.starred = convert_flag("starred");
|
||||
message.mentioned =
|
||||
convert_flag("mentioned") ||
|
||||
convert_flag("stream_wildcard_mentioned") ||
|
||||
convert_flag("topic_wildcard_mentioned");
|
||||
message.mentioned_me_directly = convert_flag("mentioned");
|
||||
message.stream_wildcard_mentioned = convert_flag("stream_wildcard_mentioned");
|
||||
message.topic_wildcard_mentioned = convert_flag("topic_wildcard_mentioned");
|
||||
message.collapsed = convert_flag("collapsed");
|
||||
message.alerted = convert_flag("has_alert_word");
|
||||
|
||||
// Once we have set boolean flags here, the `flags` attribute is
|
||||
// just a distraction, so we delete it. (All the downstream code
|
||||
// uses booleans.)
|
||||
delete message.flags;
|
||||
}
|
||||
|
||||
export function update_booleans(message, flags) {
|
||||
// When we get server flags for local echo or message edits,
|
||||
// we are vulnerable to race conditions, so only update flags
|
||||
// that are driven by message content.
|
||||
function convert_flag(flag_name) {
|
||||
return flags.includes(flag_name);
|
||||
}
|
||||
|
||||
message.mentioned =
|
||||
convert_flag("mentioned") ||
|
||||
convert_flag("stream_wildcard_mentioned") ||
|
||||
convert_flag("topic_wildcard_mentioned");
|
||||
message.mentioned_me_directly = convert_flag("mentioned");
|
||||
message.stream_wildcard_mentioned = convert_flag("stream_wildcard_mentioned");
|
||||
message.topic_wildcard_mentioned = convert_flag("topic_wildcard_mentioned");
|
||||
message.alerted = convert_flag("has_alert_word");
|
||||
}
|
||||
|
||||
export function update_property(property, value, info) {
|
||||
switch (property) {
|
||||
case "sender_full_name":
|
||||
case "small_avatar_url":
|
||||
for (const msg of stored_messages.values()) {
|
||||
if (msg.sender_id && msg.sender_id === info.user_id) {
|
||||
msg[property] = value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "stream_name":
|
||||
for (const msg of stored_messages.values()) {
|
||||
if (msg.stream_id && msg.stream_id === info.stream_id) {
|
||||
msg.display_recipient = value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "status_emoji_info":
|
||||
for (const msg of stored_messages.values()) {
|
||||
if (msg.sender_id && msg.sender_id === info.user_id) {
|
||||
msg[property] = value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export function reify_message_id({old_id, new_id}) {
|
||||
if (stored_messages.has(old_id)) {
|
||||
stored_messages.set(new_id, stored_messages.get(old_id));
|
||||
stored_messages.delete(old_id);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,277 @@
|
|||
import * as blueslip from "./blueslip";
|
||||
import * as people from "./people";
|
||||
import type {Submessage, TopicLink} from "./types";
|
||||
|
||||
const stored_messages = new Map();
|
||||
|
||||
export type MatchedMessage = {
|
||||
match_content?: string;
|
||||
match_subject?: string;
|
||||
};
|
||||
|
||||
export type MessageReactionType = "unicode_emoji" | "realm_emoji" | "zulip_extra_emoji";
|
||||
|
||||
export type DisplayRecipientUser = {
|
||||
email: string;
|
||||
full_name: string;
|
||||
id: number;
|
||||
is_mirror_dummy: boolean;
|
||||
unknown_local_echo_user?: boolean;
|
||||
};
|
||||
|
||||
export type DisplayRecipient = string | DisplayRecipientUser[];
|
||||
|
||||
export type MessageEditHistoryEntry = {
|
||||
user_id: number | null;
|
||||
timestamp: number;
|
||||
prev_content?: string;
|
||||
prev_rendered_content?: string;
|
||||
prev_rendered_content_version?: number;
|
||||
prev_stream?: number;
|
||||
prev_topic?: string;
|
||||
stream?: number;
|
||||
topic?: string;
|
||||
};
|
||||
|
||||
export type MessageReaction = {
|
||||
emoji_name: string;
|
||||
emoji_code: string;
|
||||
reaction_type: MessageReactionType;
|
||||
user_id: number;
|
||||
};
|
||||
|
||||
export type RawMessage = {
|
||||
avatar_url: string | null;
|
||||
client: string;
|
||||
content: string;
|
||||
content_type: "text/html";
|
||||
display_recipient: DisplayRecipient;
|
||||
edit_history?: MessageEditHistoryEntry[];
|
||||
id: number;
|
||||
is_me_message: boolean;
|
||||
last_edit_timestamp?: number;
|
||||
reactions: MessageReaction[];
|
||||
recipient_id: number;
|
||||
sender_email: string;
|
||||
sender_full_name: string;
|
||||
sender_id: number;
|
||||
sender_realm_str: string;
|
||||
submessages: Submessage[];
|
||||
timestamp: number;
|
||||
flags: string[];
|
||||
} & (
|
||||
| {
|
||||
type: "private";
|
||||
}
|
||||
| {
|
||||
type: "stream";
|
||||
stream_id: number;
|
||||
subject: string;
|
||||
topic_links: TopicLink[];
|
||||
}
|
||||
) &
|
||||
MatchedMessage;
|
||||
|
||||
// We add these boolean properties to Raw message in `message_store.set_message_booleans` method.
|
||||
export type MessageWithBooleans = (
|
||||
| Omit<RawMessage & {type: "private"}, "flags">
|
||||
| Omit<RawMessage & {type: "stream"}, "flags">
|
||||
) & {
|
||||
unread: boolean;
|
||||
historical: boolean;
|
||||
starred: boolean;
|
||||
mentioned: boolean;
|
||||
mentioned_me_directly: boolean;
|
||||
stream_wildcard_mentioned: boolean;
|
||||
topic_wildcard_mentioned: boolean;
|
||||
collapsed: boolean;
|
||||
alerted: boolean;
|
||||
};
|
||||
|
||||
export type MessageCleanReaction = {
|
||||
class: string;
|
||||
count: number;
|
||||
emoji_alt_code: boolean;
|
||||
emoji_code: string;
|
||||
emoji_name: string;
|
||||
is_realm_emoji: boolean;
|
||||
label: string;
|
||||
local_id: string;
|
||||
reaction_type: string;
|
||||
user_ids: number[];
|
||||
vote_text: string;
|
||||
};
|
||||
|
||||
export type Message = (
|
||||
| Omit<MessageWithBooleans & {type: "private"}, "reactions">
|
||||
| Omit<MessageWithBooleans & {type: "stream"}, "reactions">
|
||||
) & {
|
||||
// Added in `reactions.set_clean_reactions`.
|
||||
clean_reactions: Map<string, MessageCleanReaction>;
|
||||
|
||||
// Added in `message_helper.process_new_message`.
|
||||
sent_by_me: boolean;
|
||||
reply_to: string;
|
||||
display_reply_to?: string;
|
||||
|
||||
// These properties are used in `message_list_view.js`.
|
||||
starred_status: string;
|
||||
message_reactions: MessageCleanReaction[];
|
||||
url: string;
|
||||
|
||||
// Used in `markdown.js`, `server_events.js`, and `set_message_booleans`
|
||||
flags?: string[];
|
||||
} & (
|
||||
| {
|
||||
type: "private";
|
||||
is_private: true;
|
||||
is_stream: false;
|
||||
pm_with_url: string;
|
||||
to_user_ids: string;
|
||||
}
|
||||
| {
|
||||
type: "stream";
|
||||
is_private: false;
|
||||
is_stream: true;
|
||||
stream: string;
|
||||
topic: string;
|
||||
}
|
||||
);
|
||||
|
||||
export function update_message_cache(message: Message): void {
|
||||
// You should only call this from message_helper (or in tests).
|
||||
stored_messages.set(message.id, message);
|
||||
}
|
||||
|
||||
export function get_cached_message(message_id: number): Message {
|
||||
// You should only call this from message_helper.
|
||||
// Use the get() wrapper below for most other use cases.
|
||||
return stored_messages.get(message_id);
|
||||
}
|
||||
|
||||
export function clear_for_testing(): void {
|
||||
stored_messages.clear();
|
||||
}
|
||||
|
||||
export function get(message_id: number): Message | undefined {
|
||||
if (message_id === undefined || message_id === null) {
|
||||
blueslip.error("message_store.get got bad value", {message_id});
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (typeof message_id !== "number") {
|
||||
blueslip.error("message_store got non-number", {message_id});
|
||||
|
||||
// Try to soldier on, assuming the caller treats message
|
||||
// ids as strings.
|
||||
message_id = Number.parseFloat(message_id);
|
||||
}
|
||||
|
||||
return stored_messages.get(message_id);
|
||||
}
|
||||
|
||||
export function get_pm_emails(message: Message): string {
|
||||
const user_ids = people.pm_with_user_ids(message) ?? [];
|
||||
const emails = user_ids
|
||||
.map((user_id) => {
|
||||
const person = people.maybe_get_user_by_id(user_id);
|
||||
if (!person) {
|
||||
blueslip.error("Unknown user id", {user_id});
|
||||
return "?";
|
||||
}
|
||||
return person.email;
|
||||
})
|
||||
.sort();
|
||||
|
||||
return emails.join(", ");
|
||||
}
|
||||
|
||||
export function get_pm_full_names(message: Message): string {
|
||||
const user_ids = people.pm_with_user_ids(message) ?? [];
|
||||
const names = people.get_display_full_names(user_ids).sort();
|
||||
|
||||
return names.join(", ");
|
||||
}
|
||||
|
||||
export function set_message_booleans(message: Message): void {
|
||||
const flags = message.flags || [];
|
||||
|
||||
function convert_flag(flag_name: string): boolean {
|
||||
return flags.includes(flag_name);
|
||||
}
|
||||
|
||||
message.unread = !convert_flag("read");
|
||||
message.historical = convert_flag("historical");
|
||||
message.starred = convert_flag("starred");
|
||||
message.mentioned =
|
||||
convert_flag("mentioned") ||
|
||||
convert_flag("stream_wildcard_mentioned") ||
|
||||
convert_flag("topic_wildcard_mentioned");
|
||||
message.mentioned_me_directly = convert_flag("mentioned");
|
||||
message.stream_wildcard_mentioned = convert_flag("stream_wildcard_mentioned");
|
||||
message.topic_wildcard_mentioned = convert_flag("topic_wildcard_mentioned");
|
||||
message.collapsed = convert_flag("collapsed");
|
||||
message.alerted = convert_flag("has_alert_word");
|
||||
|
||||
// Once we have set boolean flags here, the `flags` attribute is
|
||||
// just a distraction, so we delete it. (All the downstream code
|
||||
// uses booleans.)
|
||||
delete message.flags;
|
||||
}
|
||||
|
||||
export function update_booleans(message: Message, flags: string[]): void {
|
||||
// When we get server flags for local echo or message edits,
|
||||
// we are vulnerable to race conditions, so only update flags
|
||||
// that are driven by message content.
|
||||
function convert_flag(flag_name: string): boolean {
|
||||
return flags.includes(flag_name);
|
||||
}
|
||||
|
||||
message.mentioned =
|
||||
convert_flag("mentioned") ||
|
||||
convert_flag("stream_wildcard_mentioned") ||
|
||||
convert_flag("topic_wildcard_mentioned");
|
||||
message.mentioned_me_directly = convert_flag("mentioned");
|
||||
message.stream_wildcard_mentioned = convert_flag("stream_wildcard_mentioned");
|
||||
message.topic_wildcard_mentioned = convert_flag("topic_wildcard_mentioned");
|
||||
message.alerted = convert_flag("has_alert_word");
|
||||
}
|
||||
|
||||
export function update_sender_full_name(user_id: number, new_name: string): void {
|
||||
for (const msg of stored_messages.values()) {
|
||||
if (msg.sender_id && msg.sender_id === user_id) {
|
||||
msg.sender_full_name = new_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function update_small_avatar_url(user_id: number, new_url: string): void {
|
||||
for (const msg of stored_messages.values()) {
|
||||
if (msg.sender_id && msg.sender_id === user_id) {
|
||||
msg.small_avatar_url = new_url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function update_stream_name(stream_id: number, new_name: string): void {
|
||||
for (const msg of stored_messages.values()) {
|
||||
if (msg.stream_id && msg.stream_id === stream_id) {
|
||||
msg.display_recipient = new_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function update_status_emoji_info(user_id: number, new_info: string): void {
|
||||
for (const msg of stored_messages.values()) {
|
||||
if (msg.sender_id && msg.sender_id === user_id) {
|
||||
msg.status_emoji_info = new_info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function reify_message_id({old_id, new_id}: {old_id: number; new_id: number}): void {
|
||||
if (stored_messages.has(old_id)) {
|
||||
stored_messages.set(new_id, stored_messages.get(old_id));
|
||||
stored_messages.delete(old_id);
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import * as typeahead from "../shared/src/typeahead";
|
|||
import * as blueslip from "./blueslip";
|
||||
import {FoldDict} from "./fold_dict";
|
||||
import {$t} from "./i18n";
|
||||
import type {DisplayRecipientUser, Message, MessageWithBooleans} from "./message_store";
|
||||
import * as message_user_ids from "./message_user_ids";
|
||||
import * as muted_users from "./muted_users";
|
||||
import {page_params} from "./page_params";
|
||||
|
@ -13,7 +14,6 @@ import * as reload_state from "./reload_state";
|
|||
import * as settings_config from "./settings_config";
|
||||
import * as settings_data from "./settings_data";
|
||||
import * as timerender from "./timerender";
|
||||
import type {DisplayRecipientUser, Message, MessageWithBooleans} from "./types";
|
||||
import {user_settings} from "./user_settings";
|
||||
import * as util from "./util";
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {FoldDict} from "./fold_dict";
|
||||
import type {Message} from "./message_store";
|
||||
import * as muted_users from "./muted_users";
|
||||
import * as people from "./people";
|
||||
import type {Message} from "./types";
|
||||
|
||||
type PMConversation = {
|
||||
user_ids_string: string;
|
||||
|
|
|
@ -13,8 +13,8 @@ import render_widgets_poll_widget_results from "../templates/widgets/poll_widget
|
|||
import * as blueslip from "./blueslip";
|
||||
import {$t} from "./i18n";
|
||||
import * as keydown_util from "./keydown_util";
|
||||
import type {Message} from "./message_store";
|
||||
import * as people from "./people";
|
||||
import type {Message} from "./types";
|
||||
|
||||
type Event = {sender_id: number; data: InboundData};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type {Message} from "./message_store";
|
||||
import * as people from "./people";
|
||||
import {get_key_from_message} from "./recent_view_util";
|
||||
import type {Message} from "./types";
|
||||
|
||||
export type ConversationData = {
|
||||
last_msg_id: number;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type {Message} from "./types";
|
||||
import type {Message} from "./message_store";
|
||||
|
||||
let is_view_visible = false;
|
||||
|
||||
|
|
138
web/src/types.ts
138
web/src/types.ts
|
@ -1,43 +1,3 @@
|
|||
// TODO/typescript: Move this to message_store
|
||||
export type MatchedMessage = {
|
||||
match_content?: string;
|
||||
match_subject?: string;
|
||||
};
|
||||
|
||||
// TODO/typescript: Move this to message_store
|
||||
export type MessageReactionType = "unicode_emoji" | "realm_emoji" | "zulip_extra_emoji";
|
||||
|
||||
// TODO/typescript: Move these types to message_store
|
||||
|
||||
export type DisplayRecipientUser = {
|
||||
email: string;
|
||||
full_name: string;
|
||||
id: number;
|
||||
is_mirror_dummy: boolean;
|
||||
unknown_local_echo_user?: boolean;
|
||||
};
|
||||
|
||||
export type DisplayRecipient = string | DisplayRecipientUser[];
|
||||
|
||||
export type MessageEditHistoryEntry = {
|
||||
user_id: number | null;
|
||||
timestamp: number;
|
||||
prev_content?: string;
|
||||
prev_rendered_content?: string;
|
||||
prev_rendered_content_version?: number;
|
||||
prev_stream?: number;
|
||||
prev_topic?: string;
|
||||
stream?: number;
|
||||
topic?: string;
|
||||
};
|
||||
|
||||
export type MessageReaction = {
|
||||
emoji_name: string;
|
||||
emoji_code: string;
|
||||
reaction_type: MessageReactionType;
|
||||
user_id: number;
|
||||
};
|
||||
|
||||
// TODO/typescript: Move this to submessage.js
|
||||
export type Submessage = {
|
||||
id: number;
|
||||
|
@ -53,104 +13,6 @@ export type TopicLink = {
|
|||
url: string;
|
||||
};
|
||||
|
||||
// TODO/typescript: Move this to message_store
|
||||
export type RawMessage = {
|
||||
avatar_url: string | null;
|
||||
client: string;
|
||||
content: string;
|
||||
content_type: "text/html";
|
||||
display_recipient: DisplayRecipient;
|
||||
edit_history?: MessageEditHistoryEntry[];
|
||||
id: number;
|
||||
is_me_message: boolean;
|
||||
last_edit_timestamp?: number;
|
||||
reactions: MessageReaction[];
|
||||
recipient_id: number;
|
||||
sender_email: string;
|
||||
sender_full_name: string;
|
||||
sender_id: number;
|
||||
sender_realm_str: string;
|
||||
submessages: Submessage[];
|
||||
timestamp: number;
|
||||
flags: string[];
|
||||
} & (
|
||||
| {
|
||||
type: "private";
|
||||
}
|
||||
| {
|
||||
type: "stream";
|
||||
stream_id: number;
|
||||
subject: string;
|
||||
topic_links: TopicLink[];
|
||||
}
|
||||
) &
|
||||
MatchedMessage;
|
||||
|
||||
// We add these boolean properties to Raw message in `message_store.set_message_booleans` method.
|
||||
export type MessageWithBooleans = (
|
||||
| Omit<RawMessage & {type: "private"}, "flags">
|
||||
| Omit<RawMessage & {type: "stream"}, "flags">
|
||||
) & {
|
||||
unread: boolean;
|
||||
historical: boolean;
|
||||
starred: boolean;
|
||||
mentioned: boolean;
|
||||
mentioned_me_directly: boolean;
|
||||
stream_wildcard_mentioned: boolean;
|
||||
topic_wildcard_mentioned: boolean;
|
||||
collapsed: boolean;
|
||||
alerted: boolean;
|
||||
};
|
||||
|
||||
// TODO/typescript: Move this to message_store
|
||||
export type MessageCleanReaction = {
|
||||
class: string;
|
||||
count: number;
|
||||
emoji_alt_code: boolean;
|
||||
emoji_code: string;
|
||||
emoji_name: string;
|
||||
is_realm_emoji: boolean;
|
||||
label: string;
|
||||
local_id: string;
|
||||
reaction_type: string;
|
||||
user_ids: number[];
|
||||
vote_text: string;
|
||||
};
|
||||
|
||||
// TODO/typescript: Move this to message_store
|
||||
export type Message = (
|
||||
| Omit<MessageWithBooleans & {type: "private"}, "reactions">
|
||||
| Omit<MessageWithBooleans & {type: "stream"}, "reactions">
|
||||
) & {
|
||||
// Added in `reactions.set_clean_reactions`.
|
||||
clean_reactions: Map<string, MessageCleanReaction>;
|
||||
|
||||
// Added in `message_helper.process_new_message`.
|
||||
sent_by_me: boolean;
|
||||
reply_to: string;
|
||||
display_reply_to?: string;
|
||||
|
||||
// These properties are used in `message_list_view.js`.
|
||||
starred_status: string;
|
||||
message_reactions: MessageCleanReaction[];
|
||||
url: string;
|
||||
} & (
|
||||
| {
|
||||
type: "private";
|
||||
is_private: true;
|
||||
is_stream: false;
|
||||
pm_with_url: string;
|
||||
to_user_ids: string;
|
||||
}
|
||||
| {
|
||||
type: "stream";
|
||||
is_private: false;
|
||||
is_stream: true;
|
||||
stream: string;
|
||||
topic: string;
|
||||
}
|
||||
);
|
||||
|
||||
// TODO/typescript: Move this to server_events_dispatch
|
||||
export type UserGroupUpdateEvent = {
|
||||
id: number;
|
||||
|
|
|
@ -2,7 +2,8 @@ import _ from "lodash";
|
|||
|
||||
import * as blueslip from "./blueslip";
|
||||
import {$t} from "./i18n";
|
||||
import type {MatchedMessage, Message, RawMessage, UpdateMessageEvent} from "./types";
|
||||
import type {MatchedMessage, Message, RawMessage} from "./message_store";
|
||||
import type {UpdateMessageEvent} from "./types";
|
||||
|
||||
// From MDN: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Math/random
|
||||
export function random_int(min: number, max: number): number {
|
||||
|
|
|
@ -336,13 +336,13 @@ test("update_property", () => {
|
|||
|
||||
assert.equal(message1.sender_full_name, alice.full_name);
|
||||
assert.equal(message2.sender_full_name, bob.full_name);
|
||||
message_store.update_property("sender_full_name", "Bobby", {user_id: bob.user_id});
|
||||
message_store.update_sender_full_name(bob.user_id, "Bobby");
|
||||
assert.equal(message1.sender_full_name, alice.full_name);
|
||||
assert.equal(message2.sender_full_name, "Bobby");
|
||||
|
||||
assert.equal(message1.small_avatar_url, "alice_url");
|
||||
assert.equal(message2.small_avatar_url, "bob_url");
|
||||
message_store.update_property("small_avatar_url", "bobby_url", {user_id: bob.user_id});
|
||||
message_store.update_small_avatar_url(bob.user_id, "bobby_url");
|
||||
assert.equal(message1.small_avatar_url, "alice_url");
|
||||
assert.equal(message2.small_avatar_url, "bobby_url");
|
||||
|
||||
|
@ -350,7 +350,7 @@ test("update_property", () => {
|
|||
assert.equal(message1.display_recipient, devel.name);
|
||||
assert.equal(message2.stream_id, denmark.stream_id);
|
||||
assert.equal(message2.display_recipient, denmark.name);
|
||||
message_store.update_property("stream_name", "Prod", {stream_id: devel.stream_id});
|
||||
message_store.update_stream_name(devel.stream_id, "Prod");
|
||||
assert.equal(message1.stream_id, devel.stream_id);
|
||||
assert.equal(message1.display_recipient, "Prod");
|
||||
assert.equal(message2.stream_id, denmark.stream_id);
|
||||
|
|
Loading…
Reference in New Issue