2017-12-16 13:33:54 +01:00
|
|
|
function send_flag_update(message, flag, op) {
|
|
|
|
channel.post({
|
|
|
|
url: '/json/messages/flags',
|
|
|
|
idempotent: true,
|
|
|
|
data: {
|
|
|
|
messages: JSON.stringify([message.id]),
|
|
|
|
flag: flag,
|
|
|
|
op: op,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
2019-05-04 04:10:05 +02:00
|
|
|
exports._unread_batch_size = 1000;
|
2017-12-16 00:04:37 +01:00
|
|
|
exports.send_read = (function () {
|
2019-11-02 00:06:25 +01:00
|
|
|
let queue = [];
|
|
|
|
let on_success;
|
|
|
|
let start;
|
2014-01-31 17:03:52 +01:00
|
|
|
function server_request() {
|
|
|
|
// Wait for server IDs before sending flags
|
2020-02-08 03:33:46 +01:00
|
|
|
const real_msgs = queue.filter(msg => !msg.locally_echoed);
|
js: Convert _.map(a, …) to a.map(…).
And convert the corresponding function expressions to arrow style
while we’re here.
import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import K from "ast-types/gen/kinds";
import fs from "fs";
import path from "path";
import process from "process";
const checkExpression = (node: n.Node): node is K.ExpressionKind =>
n.Expression.check(node);
for (const file of process.argv.slice(2)) {
console.log("Parsing", file);
const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
parser: path.extname(file) === ".ts" ? tsParser : babelParser,
});
let changed = false;
recast.visit(ast, {
visitCallExpression(path) {
const { callee, arguments: args } = path.node;
if (
n.MemberExpression.check(callee) &&
!callee.computed &&
n.Identifier.check(callee.object) &&
callee.object.name === "_" &&
n.Identifier.check(callee.property) &&
callee.property.name === "map" &&
args.length === 2 &&
checkExpression(args[0]) &&
checkExpression(args[1])
) {
const [arr, fn] = args;
path.replace(
b.callExpression(b.memberExpression(arr, b.identifier("map")), [
n.FunctionExpression.check(fn) ||
n.ArrowFunctionExpression.check(fn)
? b.arrowFunctionExpression(
fn.params,
n.BlockStatement.check(fn.body) &&
fn.body.body.length === 1 &&
n.ReturnStatement.check(fn.body.body[0])
? fn.body.body[0].argument || b.identifier("undefined")
: fn.body
)
: fn,
])
);
changed = true;
}
this.traverse(path);
},
});
if (changed) {
console.log("Writing", file);
fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
}
}
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-08 02:43:49 +01:00
|
|
|
const real_msg_ids = real_msgs.map(msg => msg.id);
|
2014-01-31 17:03:52 +01:00
|
|
|
|
|
|
|
if (real_msg_ids.length === 0) {
|
2014-03-07 23:03:46 +01:00
|
|
|
setTimeout(start, 100);
|
2014-01-31 17:03:52 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
const real_msg_ids_batch = real_msg_ids.slice(0, exports._unread_batch_size);
|
2019-05-04 04:10:05 +02:00
|
|
|
|
2014-03-07 23:04:01 +01:00
|
|
|
// 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.
|
|
|
|
|
2014-01-31 17:03:52 +01:00
|
|
|
channel.post({
|
2018-12-18 19:34:45 +01:00
|
|
|
url: '/json/messages/flags',
|
2014-01-31 17:03:52 +01:00
|
|
|
idempotent: true,
|
2019-05-04 04:10:05 +02:00
|
|
|
data: {messages: JSON.stringify(real_msg_ids_batch),
|
2018-12-18 19:34:45 +01:00
|
|
|
op: 'add',
|
|
|
|
flag: 'read'},
|
|
|
|
success: on_success,
|
2014-01-31 17:03:52 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-12-21 17:51:52 +01:00
|
|
|
start = _.throttle(server_request, 1000);
|
2014-01-31 17:03:52 +01:00
|
|
|
|
2016-12-02 14:06:06 +01:00
|
|
|
on_success = function on_success(data) {
|
2014-01-31 17:03:52 +01:00
|
|
|
if (data === undefined || data.messages === undefined) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-02-08 03:33:46 +01:00
|
|
|
queue = queue.filter(message => !data.messages.includes(message.id));
|
2014-01-31 17:03:52 +01:00
|
|
|
|
|
|
|
if (queue.length > 0) {
|
|
|
|
start();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-12-21 17:51:52 +01:00
|
|
|
function add(messages) {
|
|
|
|
queue = queue.concat(messages);
|
2014-01-31 17:03:52 +01:00
|
|
|
start();
|
|
|
|
}
|
|
|
|
|
|
|
|
return add;
|
2017-12-16 00:04:37 +01:00
|
|
|
}());
|
2014-01-31 17:03:52 +01:00
|
|
|
|
2017-12-15 23:32:36 +01:00
|
|
|
exports.save_collapsed = function (message) {
|
2018-07-03 01:41:31 +02:00
|
|
|
send_flag_update(message, 'collapsed', 'add');
|
2017-12-15 23:32:36 +01:00
|
|
|
};
|
2014-01-31 17:03:52 +01:00
|
|
|
|
2017-12-15 23:32:36 +01:00
|
|
|
exports.save_uncollapsed = function (message) {
|
2018-07-03 01:41:31 +02:00
|
|
|
send_flag_update(message, 'collapsed', 'remove');
|
2014-01-31 17:03:52 +01:00
|
|
|
};
|
|
|
|
|
2018-08-01 20:11:32 +02:00
|
|
|
// This updates the state of the starred flag in local data
|
|
|
|
// structures, and triggers a UI rerender.
|
2018-08-01 02:29:10 +02:00
|
|
|
exports.update_starred_flag = function (message_id, new_value) {
|
2019-11-02 00:06:25 +01:00
|
|
|
const message = message_store.get(message_id);
|
2018-10-12 22:51:54 +02:00
|
|
|
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;
|
|
|
|
}
|
2018-08-01 02:29:10 +02:00
|
|
|
message.starred = new_value;
|
2018-08-01 19:02:38 +02:00
|
|
|
ui.update_starred_view(message_id, new_value);
|
2018-08-01 02:29:10 +02:00
|
|
|
};
|
|
|
|
|
2018-08-01 20:09:12 +02:00
|
|
|
exports.toggle_starred_and_update_server = function (message) {
|
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;
|
|
|
|
|
2019-07-10 02:03:41 +02:00
|
|
|
// 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.
|
2018-04-04 21:32:45 +02:00
|
|
|
unread_ops.notify_server_message_read(message);
|
2018-08-01 19:02:38 +02:00
|
|
|
ui.update_starred_view(message.id, message.starred);
|
2017-12-16 13:33:54 +01:00
|
|
|
|
|
|
|
if (message.starred) {
|
|
|
|
send_flag_update(message, 'starred', 'add');
|
2018-08-17 03:46:32 +02:00
|
|
|
starred_messages.add([message.id]);
|
2017-03-19 00:30:32 +01:00
|
|
|
} else {
|
2017-12-16 13:33:54 +01:00
|
|
|
send_flag_update(message, 'starred', 'remove');
|
2018-08-17 03:46:32 +02:00
|
|
|
starred_messages.remove([message.id]);
|
2017-03-19 00:30:32 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-02-22 12:28:29 +01:00
|
|
|
exports.unstar_all_messages = function () {
|
2019-11-02 00:06:25 +01:00
|
|
|
const starred_msg_ids = starred_messages.get_starred_msg_ids();
|
2019-02-22 12:28:29 +01:00
|
|
|
channel.post({
|
|
|
|
url: '/json/messages/flags',
|
|
|
|
idempotent: true,
|
|
|
|
data: {
|
|
|
|
messages: JSON.stringify(starred_msg_ids),
|
|
|
|
flag: 'starred',
|
|
|
|
op: 'remove',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2019-10-25 09:45:13 +02:00
|
|
|
window.message_flags = exports;
|