zulip/static/js/message_flags.js

151 lines
4.7 KiB
JavaScript
Raw Normal View History

import _ from "lodash";
import * as channel from "./channel";
import * as message_store from "./message_store";
import * as starred_messages from "./starred_messages";
import * as ui from "./ui";
import * as unread_ops from "./unread_ops";
function send_flag_update_for_messages(msg_ids, flag, op) {
Simplify/unify starring messages from the frontend. We now do all of the main logic for starring/unstarring a message in `message_flags.toggle_starred`: * mark the message as read (just in case) * update the UI (i.e. the green star in the message) * update the server The calling code in both the click handler and the hotkey handler remains simple--they just handle minor details like finding the message and clearing popovers. For updating the server, we now call the new `send_flag_update` helper. And we continue to delegate some of the logic to `ui.update_starred`, but we remove some code there that's now pushed up to `message_flags.toggle_starred`. This change should be mostly transparent to users, but it does remove some inconsistent behaviors between the click handler and the hotkey handler. Before this change, the click handler was more aggressive about updating the UI and marking the message as read. For people using the "*" key to star/unstar, they probably would only have noticed different behavior on a slow connection or in an edge case scenario where only half of the message was onscreen. More importantly, by simplifying how we talk to the server, this eliminated up to a one-second lag due to the debounce logic in the batch_updater code. The complicated debounce logic is only really needed for batch-updating "read" messages, and it was overkill and sluggish for starring messages. Last but not least, we add defensive code for the local echo case. (Users have to wait till the message gets acked to star it.)
2017-12-16 13:33:54 +01:00
channel.post({
url: "/json/messages/flags",
Simplify/unify starring messages from the frontend. We now do all of the main logic for starring/unstarring a message in `message_flags.toggle_starred`: * mark the message as read (just in case) * update the UI (i.e. the green star in the message) * update the server The calling code in both the click handler and the hotkey handler remains simple--they just handle minor details like finding the message and clearing popovers. For updating the server, we now call the new `send_flag_update` helper. And we continue to delegate some of the logic to `ui.update_starred`, but we remove some code there that's now pushed up to `message_flags.toggle_starred`. This change should be mostly transparent to users, but it does remove some inconsistent behaviors between the click handler and the hotkey handler. Before this change, the click handler was more aggressive about updating the UI and marking the message as read. For people using the "*" key to star/unstar, they probably would only have noticed different behavior on a slow connection or in an edge case scenario where only half of the message was onscreen. More importantly, by simplifying how we talk to the server, this eliminated up to a one-second lag due to the debounce logic in the batch_updater code. The complicated debounce logic is only really needed for batch-updating "read" messages, and it was overkill and sluggish for starring messages. Last but not least, we add defensive code for the local echo case. (Users have to wait till the message gets acked to star it.)
2017-12-16 13:33:54 +01:00
idempotent: true,
data: {
messages: JSON.stringify(msg_ids),
flag,
op,
Simplify/unify starring messages from the frontend. We now do all of the main logic for starring/unstarring a message in `message_flags.toggle_starred`: * mark the message as read (just in case) * update the UI (i.e. the green star in the message) * update the server The calling code in both the click handler and the hotkey handler remains simple--they just handle minor details like finding the message and clearing popovers. For updating the server, we now call the new `send_flag_update` helper. And we continue to delegate some of the logic to `ui.update_starred`, but we remove some code there that's now pushed up to `message_flags.toggle_starred`. This change should be mostly transparent to users, but it does remove some inconsistent behaviors between the click handler and the hotkey handler. Before this change, the click handler was more aggressive about updating the UI and marking the message as read. For people using the "*" key to star/unstar, they probably would only have noticed different behavior on a slow connection or in an edge case scenario where only half of the message was onscreen. More importantly, by simplifying how we talk to the server, this eliminated up to a one-second lag due to the debounce logic in the batch_updater code. The complicated debounce logic is only really needed for batch-updating "read" messages, and it was overkill and sluggish for starring messages. Last but not least, we add defensive code for the local echo case. (Users have to wait till the message gets acked to star it.)
2017-12-16 13:33:54 +01:00
},
});
}
export const _unread_batch_size = 1000;
export const send_read = (function () {
let queue = [];
let on_success;
let start;
function server_request() {
// Wait for server IDs before sending flags
const real_msgs = queue.filter((msg) => !msg.locally_echoed);
const real_msg_ids = real_msgs.map((msg) => msg.id);
if (real_msg_ids.length === 0) {
setTimeout(start, 100);
return;
}
const real_msg_ids_batch = real_msg_ids.slice(0, _unread_batch_size);
// We have some real IDs. If there are any left in the queue when this
// call finishes, they will be handled in the success callback.
channel.post({
url: "/json/messages/flags",
idempotent: true,
data: {messages: JSON.stringify(real_msg_ids_batch), op: "add", flag: "read"},
success: on_success,
});
}
start = _.throttle(server_request, 1000);
on_success = function on_success(data) {
if (data === undefined || data.messages === undefined) {
return;
}
queue = queue.filter((message) => !data.messages.includes(message.id));
if (queue.length > 0) {
start();
}
};
function add(messages) {
queue = queue.concat(messages);
start();
}
return add;
})();
export function save_collapsed(message) {
send_flag_update_for_messages([message.id], "collapsed", "add");
}
export function save_uncollapsed(message) {
send_flag_update_for_messages([message.id], "collapsed", "remove");
}
// This updates the state of the starred flag in local data
// structures, and triggers a UI rerender.
export function update_starred_flag(message_id, new_value) {
const message = message_store.get(message_id);
if (message === undefined) {
// If we don't have the message locally, do nothing; if later
// we fetch it, it'll come with the correct `starred` state.
return;
}
message.starred = new_value;
ui.update_starred_view(message_id, new_value);
}
export function toggle_starred_and_update_server(message) {
Simplify/unify starring messages from the frontend. We now do all of the main logic for starring/unstarring a message in `message_flags.toggle_starred`: * mark the message as read (just in case) * update the UI (i.e. the green star in the message) * update the server The calling code in both the click handler and the hotkey handler remains simple--they just handle minor details like finding the message and clearing popovers. For updating the server, we now call the new `send_flag_update` helper. And we continue to delegate some of the logic to `ui.update_starred`, but we remove some code there that's now pushed up to `message_flags.toggle_starred`. This change should be mostly transparent to users, but it does remove some inconsistent behaviors between the click handler and the hotkey handler. Before this change, the click handler was more aggressive about updating the UI and marking the message as read. For people using the "*" key to star/unstar, they probably would only have noticed different behavior on a slow connection or in an edge case scenario where only half of the message was onscreen. More importantly, by simplifying how we talk to the server, this eliminated up to a one-second lag due to the debounce logic in the batch_updater code. The complicated debounce logic is only really needed for batch-updating "read" messages, and it was overkill and sluggish for starring messages. Last but not least, we add defensive code for the local echo case. (Users have to wait till the message gets acked to star it.)
2017-12-16 13:33:54 +01:00
if (message.locally_echoed) {
// This is defensive code for when you hit the "*" key
// before we get a server ack. It's rare that somebody
// can star this quickly, and we don't have a good way
// to tell the server which message was starred.
return;
}
message.starred = !message.starred;
// Unlike most calls to mark messages as read, we don't check
// msg_list.can_mark_messages_read, because starring a message is an
// explicit interaction and we'd like to preserve the user
// expectation invariant that all starred messages are read.
unread_ops.notify_server_message_read(message);
ui.update_starred_view(message.id, message.starred);
Simplify/unify starring messages from the frontend. We now do all of the main logic for starring/unstarring a message in `message_flags.toggle_starred`: * mark the message as read (just in case) * update the UI (i.e. the green star in the message) * update the server The calling code in both the click handler and the hotkey handler remains simple--they just handle minor details like finding the message and clearing popovers. For updating the server, we now call the new `send_flag_update` helper. And we continue to delegate some of the logic to `ui.update_starred`, but we remove some code there that's now pushed up to `message_flags.toggle_starred`. This change should be mostly transparent to users, but it does remove some inconsistent behaviors between the click handler and the hotkey handler. Before this change, the click handler was more aggressive about updating the UI and marking the message as read. For people using the "*" key to star/unstar, they probably would only have noticed different behavior on a slow connection or in an edge case scenario where only half of the message was onscreen. More importantly, by simplifying how we talk to the server, this eliminated up to a one-second lag due to the debounce logic in the batch_updater code. The complicated debounce logic is only really needed for batch-updating "read" messages, and it was overkill and sluggish for starring messages. Last but not least, we add defensive code for the local echo case. (Users have to wait till the message gets acked to star it.)
2017-12-16 13:33:54 +01:00
if (message.starred) {
send_flag_update_for_messages([message.id], "starred", "add");
starred_messages.add([message.id]);
} else {
send_flag_update_for_messages([message.id], "starred", "remove");
starred_messages.remove([message.id]);
}
}
export function unstar_all_messages() {
const starred_msg_ids = starred_messages.get_starred_msg_ids();
send_flag_update_for_messages(starred_msg_ids, "starred", "remove");
}
export function unstar_all_messages_in_topic(stream_id, topic) {
const data = {
anchor: "newest",
// In the unlikely event the user has >1000 starred messages
// in a topic, this won't find them all. This is probably an
// acceptable bug; one can do it multiple times, and we avoid
// creating an API endpoint just for this very minor feature.
num_before: 1000,
num_after: 0,
narrow: JSON.stringify([
{operator: "stream", operand: stream_id},
{operator: "topic", operand: topic},
{operator: "is", operand: "starred"},
]),
};
channel.get({
url: "/json/messages",
data,
idempotent: true,
success(data) {
const messages = data.messages;
const starred_message_ids = messages.map((message) => message.id);
send_flag_update_for_messages(starred_message_ids, "starred", "remove");
},
});
}