2013-08-15 21:11:07 +02:00
|
|
|
var stream_data = (function () {
|
|
|
|
|
|
|
|
var exports = {};
|
|
|
|
|
2013-09-16 23:47:05 +02:00
|
|
|
|
|
|
|
// The stream_info variable maps stream names to stream properties objects
|
|
|
|
// Call clear_subscriptions() to initialize it.
|
|
|
|
var stream_info;
|
2014-02-05 20:35:16 +01:00
|
|
|
var subs_by_stream_id;
|
2017-05-14 15:39:02 +02:00
|
|
|
var recent_topics = new Dict(); // stream_id -> array of objects
|
2013-09-16 23:47:05 +02:00
|
|
|
|
2017-05-11 21:49:38 +02:00
|
|
|
var stream_ids_by_name = new Dict({fold_case: true});
|
|
|
|
|
2017-03-21 21:10:20 +01:00
|
|
|
var defaults = {};
|
|
|
|
|
2013-09-16 23:47:05 +02:00
|
|
|
exports.clear_subscriptions = function () {
|
|
|
|
stream_info = new Dict({fold_case: true});
|
2014-02-05 20:35:16 +01:00
|
|
|
subs_by_stream_id = new Dict();
|
2013-09-16 23:47:05 +02:00
|
|
|
};
|
2016-06-04 22:40:25 +02:00
|
|
|
|
2013-09-16 23:47:05 +02:00
|
|
|
exports.clear_subscriptions();
|
2013-08-15 21:11:07 +02:00
|
|
|
|
2017-04-28 15:38:02 +02:00
|
|
|
exports.is_active = function (sub) {
|
2017-05-14 15:39:02 +02:00
|
|
|
return recent_topics.has(sub.stream_id) || sub.newly_subscribed;
|
2016-10-28 17:18:56 +02:00
|
|
|
};
|
2013-08-15 21:11:07 +02:00
|
|
|
|
2017-03-05 00:35:45 +01:00
|
|
|
exports.rename_sub = function (sub, new_name) {
|
2016-10-30 17:33:23 +01:00
|
|
|
var old_name = sub.name;
|
2017-05-11 21:49:38 +02:00
|
|
|
|
|
|
|
stream_ids_by_name.set(old_name, sub.stream_id);
|
|
|
|
|
2016-10-30 17:33:23 +01:00
|
|
|
sub.name = new_name;
|
|
|
|
stream_info.del(old_name);
|
|
|
|
stream_info.set(new_name, sub);
|
|
|
|
};
|
|
|
|
|
2017-01-20 23:04:40 +01:00
|
|
|
exports.subscribe_myself = function (sub) {
|
|
|
|
var user_id = people.my_current_user_id();
|
|
|
|
exports.add_subscriber(sub.name, user_id);
|
|
|
|
sub.subscribed = true;
|
2017-04-28 15:59:30 +02:00
|
|
|
sub.newly_subscribed = true;
|
2017-01-20 23:04:40 +01:00
|
|
|
};
|
|
|
|
|
2016-11-09 16:26:35 +01:00
|
|
|
exports.unsubscribe_myself = function (sub) {
|
|
|
|
// Remove user from subscriber's list
|
2017-01-19 23:52:09 +01:00
|
|
|
var user_id = people.my_current_user_id();
|
2016-11-09 16:05:30 +01:00
|
|
|
exports.remove_subscriber(sub.name, user_id);
|
2016-11-09 16:26:35 +01:00
|
|
|
sub.subscribed = false;
|
2017-04-28 15:59:30 +02:00
|
|
|
sub.newly_subscribed = false;
|
2016-11-09 16:26:35 +01:00
|
|
|
};
|
|
|
|
|
2013-08-15 21:11:07 +02:00
|
|
|
exports.add_sub = function (stream_name, sub) {
|
2016-03-14 06:38:43 +01:00
|
|
|
if (!_.has(sub, 'subscribers')) {
|
2016-10-30 15:47:20 +01:00
|
|
|
sub.subscribers = Dict.from_array([]);
|
2016-03-14 06:38:43 +01:00
|
|
|
}
|
|
|
|
|
2013-09-16 23:47:05 +02:00
|
|
|
stream_info.set(stream_name, sub);
|
2014-02-05 20:35:16 +01:00
|
|
|
subs_by_stream_id.set(sub.stream_id, sub);
|
2013-08-15 21:11:07 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
exports.get_sub = function (stream_name) {
|
2013-09-16 23:47:05 +02:00
|
|
|
return stream_info.get(stream_name);
|
2013-08-15 21:11:07 +02:00
|
|
|
};
|
|
|
|
|
2014-02-05 20:35:16 +01:00
|
|
|
exports.get_sub_by_id = function (stream_id) {
|
|
|
|
return subs_by_stream_id.get(stream_id);
|
|
|
|
};
|
|
|
|
|
2017-05-11 21:49:38 +02:00
|
|
|
exports.get_stream_id = function (name) {
|
|
|
|
// Note: Only use this function for situations where
|
|
|
|
// you are comfortable with a user dealing with an
|
|
|
|
// old name of a stream (from prior to a rename).
|
|
|
|
var sub = stream_info.get(name);
|
|
|
|
|
|
|
|
if (sub) {
|
|
|
|
return sub.stream_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
var stream_id = stream_ids_by_name.get(name);
|
|
|
|
return stream_id;
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.get_sub_by_name = function (name) {
|
|
|
|
// Note: Only use this function for situations where
|
|
|
|
// you are comfortable with a user dealing with an
|
|
|
|
// old name of a stream (from prior to a rename).
|
|
|
|
|
|
|
|
var sub = stream_info.get(name);
|
|
|
|
|
|
|
|
if (sub) {
|
|
|
|
return sub;
|
|
|
|
}
|
|
|
|
|
|
|
|
var stream_id = stream_ids_by_name.get(name);
|
|
|
|
|
|
|
|
if (!stream_id) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return subs_by_stream_id.get(stream_id);
|
|
|
|
};
|
|
|
|
|
2017-02-16 03:47:08 +01:00
|
|
|
exports.delete_sub = function (stream_id) {
|
|
|
|
var sub = subs_by_stream_id.get(stream_id);
|
|
|
|
if (!sub) {
|
|
|
|
blueslip.warn('Failed to delete stream ' + stream_id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
subs_by_stream_id.del(stream_id);
|
|
|
|
stream_info.del(sub.name);
|
2013-08-21 23:21:31 +02:00
|
|
|
};
|
|
|
|
|
2013-10-25 16:59:52 +02:00
|
|
|
exports.subscribed_subs = function () {
|
2013-08-15 21:11:07 +02:00
|
|
|
return _.where(stream_info.values(), {subscribed: true});
|
2013-10-25 16:59:52 +02:00
|
|
|
};
|
2013-08-15 21:11:07 +02:00
|
|
|
|
2016-10-25 21:45:19 +02:00
|
|
|
exports.unsubscribed_subs = function () {
|
|
|
|
return _.where(stream_info.values(), {subscribed: false});
|
|
|
|
};
|
|
|
|
|
2013-08-15 21:11:07 +02:00
|
|
|
exports.subscribed_streams = function () {
|
2013-10-25 16:59:52 +02:00
|
|
|
return _.pluck(exports.subscribed_subs(), 'name');
|
2013-08-15 21:11:07 +02:00
|
|
|
};
|
|
|
|
|
2017-03-21 21:10:20 +01:00
|
|
|
exports.invite_streams = function () {
|
|
|
|
var invite_list = exports.subscribed_streams();
|
|
|
|
var default_list = _.pluck(page_params.realm_default_streams, 'name');
|
|
|
|
return _.union(invite_list, default_list);
|
|
|
|
};
|
|
|
|
|
2013-08-15 21:11:07 +02:00
|
|
|
exports.get_colors = function () {
|
2013-10-25 16:59:52 +02:00
|
|
|
return _.pluck(exports.subscribed_subs(), 'color');
|
2013-08-15 21:11:07 +02:00
|
|
|
};
|
|
|
|
|
2016-03-14 06:38:43 +01:00
|
|
|
exports.update_subscribers_count = function (sub) {
|
|
|
|
var count = sub.subscribers.num_items();
|
|
|
|
sub.subscriber_count = count;
|
|
|
|
};
|
|
|
|
|
2017-06-29 15:35:34 +02:00
|
|
|
exports.get_subscriber_count = function (stream_name) {
|
|
|
|
var sub = exports.get_sub_by_name(stream_name);
|
|
|
|
if (sub === undefined) {
|
|
|
|
blueslip.warn('We got a get_subscriber_count count call for a non-existent stream.');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!sub.subscribers) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return sub.subscribers.num_items();
|
|
|
|
};
|
|
|
|
|
2017-04-28 17:55:22 +02:00
|
|
|
exports.render_stream_description = function (sub) {
|
|
|
|
if (sub.description) {
|
|
|
|
sub.rendered_description = marked(sub.description).replace('<p>', '').replace('</p>', '');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.update_calculated_fields = function (sub) {
|
|
|
|
sub.is_admin = page_params.is_admin;
|
|
|
|
sub.can_make_public = page_params.is_admin && sub.invite_only && sub.subscribed;
|
|
|
|
sub.can_make_private = page_params.is_admin && !sub.invite_only;
|
|
|
|
sub.preview_url = narrow.by_stream_uri(sub.name);
|
|
|
|
exports.render_stream_description(sub);
|
|
|
|
exports.update_subscribers_count(sub);
|
|
|
|
};
|
|
|
|
|
2013-08-15 21:11:07 +02:00
|
|
|
exports.all_subscribed_streams_are_in_home_view = function () {
|
2013-10-25 16:59:52 +02:00
|
|
|
return _.every(exports.subscribed_subs(), function (sub) {
|
2016-12-01 13:30:30 +01:00
|
|
|
return sub.in_home_view;
|
|
|
|
});
|
2013-08-15 21:11:07 +02:00
|
|
|
};
|
|
|
|
|
2014-01-15 20:59:31 +01:00
|
|
|
exports.home_view_stream_names = function () {
|
|
|
|
var home_view_subs = _.filter(exports.subscribed_subs(), function (sub) {
|
|
|
|
return sub.in_home_view;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
return _.map(home_view_subs, function (sub) {
|
|
|
|
return sub.name;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2013-08-15 21:11:07 +02:00
|
|
|
exports.canonicalized_name = function (stream_name) {
|
|
|
|
return stream_name.toString().toLowerCase();
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.get_color = function (stream_name) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
|
|
|
if (sub === undefined) {
|
|
|
|
return stream_color.default_color;
|
|
|
|
}
|
|
|
|
return sub.color;
|
|
|
|
};
|
|
|
|
|
2017-05-13 20:54:53 +02:00
|
|
|
exports.in_home_view = function (stream_id) {
|
|
|
|
var sub = exports.get_sub_by_id(stream_id);
|
|
|
|
return sub !== undefined && sub.in_home_view;
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.name_in_home_view = function (stream_name) {
|
2013-08-15 21:11:07 +02:00
|
|
|
var sub = exports.get_sub(stream_name);
|
|
|
|
return sub !== undefined && sub.in_home_view;
|
|
|
|
};
|
|
|
|
|
2017-05-13 20:54:53 +02:00
|
|
|
exports.notifications_in_home_view = function () {
|
|
|
|
// TODO: add page_params.notifications_stream_id
|
|
|
|
return exports.name_in_home_view(page_params.notifications_stream);
|
|
|
|
};
|
|
|
|
|
2013-08-15 21:11:07 +02:00
|
|
|
exports.is_subscribed = function (stream_name) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
|
|
|
return sub !== undefined && sub.subscribed;
|
|
|
|
};
|
|
|
|
|
2017-05-14 16:32:18 +02:00
|
|
|
exports.id_is_subscribed = function (stream_id) {
|
|
|
|
var sub = subs_by_stream_id.get(stream_id);
|
|
|
|
return sub !== undefined && sub.subscribed;
|
|
|
|
};
|
|
|
|
|
2013-08-15 21:11:07 +02:00
|
|
|
exports.get_invite_only = function (stream_name) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
|
|
|
if (sub === undefined) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return sub.invite_only;
|
|
|
|
};
|
|
|
|
|
2017-03-21 21:10:20 +01:00
|
|
|
exports.get_default_status = function (stream_name) {
|
|
|
|
return defaults.hasOwnProperty(stream_name);
|
|
|
|
};
|
|
|
|
|
2013-08-19 19:25:44 +02:00
|
|
|
exports.get_name = function (stream_name) {
|
|
|
|
// This returns the actual name of a stream if we are subscribed to
|
|
|
|
// it (i.e "Denmark" vs. "denmark"), while falling thru to
|
|
|
|
// stream_name if we don't have a subscription. (Stream names
|
|
|
|
// are case-insensitive, but we try to display the actual name
|
|
|
|
// when we know it.)
|
2017-05-11 23:25:42 +02:00
|
|
|
//
|
|
|
|
// This function will also do the right thing if we have
|
|
|
|
// an old stream name in memory for a recently renamed stream.
|
|
|
|
var sub = exports.get_sub_by_name(stream_name);
|
2013-08-19 19:25:44 +02:00
|
|
|
if (sub === undefined) {
|
|
|
|
return stream_name;
|
|
|
|
}
|
|
|
|
return sub.name;
|
|
|
|
};
|
|
|
|
|
2016-10-30 15:47:20 +01:00
|
|
|
exports.set_subscribers = function (sub, user_ids) {
|
|
|
|
sub.subscribers = Dict.from_array(user_ids || []);
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.set_subscriber_emails = function (sub, emails) {
|
|
|
|
_.each(emails, function (email) {
|
|
|
|
var user_id = people.get_user_id(email);
|
|
|
|
if (!user_id) {
|
|
|
|
blueslip.error("We tried to set invalid subscriber: " + email);
|
|
|
|
} else {
|
|
|
|
sub.subscribers.set(user_id, true);
|
|
|
|
}
|
|
|
|
});
|
2013-09-16 22:26:53 +02:00
|
|
|
};
|
|
|
|
|
2016-11-08 16:06:50 +01:00
|
|
|
exports.add_subscriber = function (stream_name, user_id) {
|
2013-09-07 02:48:44 +02:00
|
|
|
var sub = exports.get_sub(stream_name);
|
2016-10-15 21:13:09 +02:00
|
|
|
if (typeof sub === 'undefined') {
|
|
|
|
blueslip.warn("We got an add_subscriber call for a non-existent stream.");
|
2017-03-03 23:14:06 +01:00
|
|
|
return false;
|
2013-09-07 02:48:44 +02:00
|
|
|
}
|
2016-11-08 16:06:50 +01:00
|
|
|
var person = people.get_person_from_user_id(user_id);
|
|
|
|
if (person === undefined) {
|
|
|
|
blueslip.error("We tried to add invalid subscriber: " + user_id);
|
2017-03-03 23:14:06 +01:00
|
|
|
return false;
|
2016-10-30 15:47:20 +01:00
|
|
|
}
|
|
|
|
sub.subscribers.set(user_id, true);
|
2017-03-03 23:14:06 +01:00
|
|
|
|
|
|
|
return true;
|
2013-09-07 02:48:44 +02:00
|
|
|
};
|
|
|
|
|
2016-11-09 16:05:30 +01:00
|
|
|
exports.remove_subscriber = function (stream_name, user_id) {
|
2013-09-07 02:48:44 +02:00
|
|
|
var sub = exports.get_sub(stream_name);
|
2016-10-25 20:06:25 +02:00
|
|
|
if (typeof sub === 'undefined') {
|
|
|
|
blueslip.warn("We got a remove_subscriber call for a non-existent stream " + stream_name);
|
2017-03-03 23:14:06 +01:00
|
|
|
return false;
|
2013-09-07 02:48:44 +02:00
|
|
|
}
|
2016-11-09 16:05:30 +01:00
|
|
|
if (!sub.subscribers.has(user_id)) {
|
|
|
|
blueslip.warn("We tried to remove invalid subscriber: " + user_id);
|
2017-03-03 23:14:06 +01:00
|
|
|
return false;
|
2016-10-30 15:47:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
sub.subscribers.del(user_id);
|
2017-03-03 23:14:06 +01:00
|
|
|
|
|
|
|
return true;
|
2013-09-07 02:48:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
exports.user_is_subscribed = function (stream_name, user_email) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
2013-09-07 04:22:18 +02:00
|
|
|
if (typeof sub === 'undefined' || !sub.subscribed) {
|
|
|
|
// If we don't know about the stream, or we ourselves are not
|
|
|
|
// subscribed, we can't keep track of the subscriber list in general,
|
|
|
|
// so we return undefined (treated as falsy if not explicitly handled).
|
2013-09-24 00:13:02 +02:00
|
|
|
blueslip.warn("We got a user_is_subscribed call for a non-existent or unsubscribed stream.");
|
2013-09-07 02:48:44 +02:00
|
|
|
return undefined;
|
|
|
|
}
|
2016-10-30 15:47:20 +01:00
|
|
|
var user_id = people.get_user_id(user_email);
|
|
|
|
if (!user_id) {
|
|
|
|
blueslip.warn("Bad email passed to user_is_subscribed: " + user_email);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return sub.subscribers.has(user_id);
|
2013-09-07 02:48:44 +02:00
|
|
|
};
|
|
|
|
|
2016-10-15 21:10:10 +02:00
|
|
|
exports.create_streams = function (streams) {
|
|
|
|
_.each(streams, function (stream) {
|
2016-10-30 15:47:20 +01:00
|
|
|
// We handle subscriber stuff in other events.
|
2016-10-15 21:10:10 +02:00
|
|
|
var attrs = _.defaults(stream, {
|
2016-10-30 15:47:20 +01:00
|
|
|
subscribers: [],
|
2017-01-12 00:17:43 +01:00
|
|
|
subscribed: false,
|
2016-10-15 21:10:10 +02:00
|
|
|
});
|
|
|
|
exports.create_sub_from_server_data(stream.name, attrs);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2016-10-15 20:17:32 +02:00
|
|
|
exports.create_sub_from_server_data = function (stream_name, attrs) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
|
|
|
if (sub !== undefined) {
|
|
|
|
// We've already created this subscription, no need to continue.
|
|
|
|
return sub;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!attrs.stream_id) {
|
|
|
|
// fail fast (blueslip.fatal will throw an error on our behalf)
|
|
|
|
blueslip.fatal("We cannot create a sub without a stream_id");
|
|
|
|
return; // this line is never actually reached
|
|
|
|
}
|
|
|
|
|
|
|
|
// Our internal data structure for subscriptions is mostly plain dictionaries,
|
|
|
|
// so we just reuse the attrs that are passed in to us, but we encapsulate how
|
|
|
|
// we handle subscribers.
|
2016-10-30 15:47:20 +01:00
|
|
|
var subscriber_user_ids = attrs.subscribers;
|
2016-10-15 20:17:32 +02:00
|
|
|
var raw_attrs = _.omit(attrs, 'subscribers');
|
|
|
|
|
|
|
|
sub = _.defaults(raw_attrs, {
|
|
|
|
name: stream_name,
|
2017-04-20 08:03:44 +02:00
|
|
|
render_subscribers: !page_params.realm_is_zephyr_mirror_realm || attrs.invite_only === true,
|
2016-10-15 20:17:32 +02:00
|
|
|
subscribed: true,
|
2017-04-28 15:59:30 +02:00
|
|
|
newly_subscribed: false,
|
2016-10-15 20:17:32 +02:00
|
|
|
in_home_view: true,
|
|
|
|
invite_only: false,
|
2017-04-29 07:01:46 +02:00
|
|
|
desktop_notifications: page_params.enable_stream_desktop_notifications,
|
2017-04-29 06:56:58 +02:00
|
|
|
audible_notifications: page_params.enable_stream_sounds,
|
2017-01-12 00:17:43 +01:00
|
|
|
description: '',
|
2016-10-15 20:17:32 +02:00
|
|
|
});
|
|
|
|
|
2016-10-30 15:47:20 +01:00
|
|
|
exports.set_subscribers(sub, subscriber_user_ids);
|
2016-10-15 20:17:32 +02:00
|
|
|
|
|
|
|
if (!sub.color) {
|
|
|
|
var used_colors = exports.get_colors();
|
|
|
|
sub.color = stream_color.pick_color(used_colors);
|
|
|
|
}
|
|
|
|
|
|
|
|
exports.add_sub(stream_name, sub);
|
|
|
|
|
|
|
|
return sub;
|
|
|
|
};
|
|
|
|
|
2016-10-17 15:53:06 +02:00
|
|
|
exports.receives_desktop_notifications = function (stream_name) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
|
|
|
if (sub === undefined) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return sub.desktop_notifications;
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.receives_audible_notifications = function (stream_name) {
|
|
|
|
var sub = exports.get_sub(stream_name);
|
|
|
|
if (sub === undefined) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return sub.audible_notifications;
|
|
|
|
};
|
|
|
|
|
2016-12-02 15:16:33 +01:00
|
|
|
exports.process_message_for_recent_topics = function process_message_for_recent_topics(
|
|
|
|
message, remove_message) {
|
2016-10-28 17:31:18 +02:00
|
|
|
var current_timestamp = 0;
|
|
|
|
var count = 0;
|
2017-05-14 15:39:02 +02:00
|
|
|
var stream_id = message.stream_id;
|
2017-07-24 15:15:28 +02:00
|
|
|
var canon_topic = message.subject.toLowerCase();
|
2016-10-28 17:31:18 +02:00
|
|
|
|
2017-05-14 15:39:02 +02:00
|
|
|
var recents = recent_topics.get(stream_id) || [];
|
2016-10-28 17:31:18 +02:00
|
|
|
|
2017-05-14 15:39:02 +02:00
|
|
|
recents = _.filter(recents, function (item) {
|
2017-07-24 15:15:28 +02:00
|
|
|
var is_duplicate = (
|
|
|
|
item.name.toLowerCase() === canon_topic);
|
2017-05-14 15:39:02 +02:00
|
|
|
if (is_duplicate) {
|
|
|
|
current_timestamp = item.timestamp;
|
|
|
|
count = item.count;
|
|
|
|
}
|
|
|
|
return !is_duplicate;
|
|
|
|
});
|
2016-10-28 17:31:18 +02:00
|
|
|
|
|
|
|
if (remove_message !== undefined) {
|
|
|
|
count = count - 1;
|
|
|
|
} else {
|
|
|
|
count = count + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count !== 0) {
|
2017-07-24 15:15:28 +02:00
|
|
|
recents.push({name: message.subject,
|
2016-10-28 17:31:18 +02:00
|
|
|
count: count,
|
|
|
|
timestamp: Math.max(message.timestamp, current_timestamp)});
|
|
|
|
}
|
|
|
|
|
|
|
|
recents.sort(function (a, b) {
|
|
|
|
return b.timestamp - a.timestamp;
|
|
|
|
});
|
|
|
|
|
2017-05-14 15:39:02 +02:00
|
|
|
recent_topics.set(stream_id, recents);
|
2016-10-28 17:31:18 +02:00
|
|
|
};
|
|
|
|
|
2016-10-25 21:45:19 +02:00
|
|
|
exports.get_streams_for_settings_page = function () {
|
2016-10-17 17:48:56 +02:00
|
|
|
// Build up our list of subscribed streams from the data we already have.
|
|
|
|
var subscribed_rows = exports.subscribed_subs();
|
2016-10-25 21:45:19 +02:00
|
|
|
var unsubscribed_rows = exports.unsubscribed_subs();
|
2016-10-17 17:48:56 +02:00
|
|
|
|
|
|
|
// Sort and combine all our streams.
|
|
|
|
function by_name(a,b) {
|
|
|
|
return util.strcmp(a.name, b.name);
|
|
|
|
}
|
|
|
|
subscribed_rows.sort(by_name);
|
|
|
|
unsubscribed_rows.sort(by_name);
|
2016-11-01 22:32:10 +01:00
|
|
|
var all_subs = unsubscribed_rows.concat(subscribed_rows);
|
2016-10-17 17:48:56 +02:00
|
|
|
|
2016-03-14 06:38:43 +01:00
|
|
|
// Add in admin options and stream counts.
|
2016-10-17 17:48:56 +02:00
|
|
|
_.each(all_subs, function (sub) {
|
2017-04-28 17:55:22 +02:00
|
|
|
exports.update_calculated_fields(sub);
|
2016-10-17 17:48:56 +02:00
|
|
|
});
|
|
|
|
|
2017-04-28 17:55:22 +02:00
|
|
|
return all_subs;
|
2016-10-17 17:48:56 +02:00
|
|
|
};
|
2016-10-17 16:38:15 +02:00
|
|
|
|
Clean up startup code for streams.
The startup code in subs.js used to intermingle data
stuff and UI stuff in a loop inside a called function,
which made the code hard to reason about.
Now there is a clear separation of concerns, with these methods
being called in succession:
stream_data.initialize_from_page_params();
stream_list.create_initial_sidebar_rows();
The first method was mostly extracted from subs.js, but I simplified
some things, like not needing to make a copy of the hashes
we were passed in, plus I now garbage collect email_dict. Also,
the code path that initialize_from_page_params() mostly replaces
used to call create_sub(), which fired a trigger, but now it
just does data stuff.
Once the data structure is built up, it's a very simple matter
to build the initial sidebar rows, and that's what the second
method does.
2016-10-17 19:34:58 +02:00
|
|
|
exports.initialize_from_page_params = function () {
|
|
|
|
function populate_subscriptions(subs, subscribed) {
|
|
|
|
subs.forEach(function (sub) {
|
|
|
|
var stream_name = sub.name;
|
|
|
|
sub.subscribed = subscribed;
|
|
|
|
|
|
|
|
exports.create_sub_from_server_data(stream_name, sub);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-03-21 21:10:20 +01:00
|
|
|
page_params.realm_default_streams.forEach(function (stream) {
|
|
|
|
defaults[stream.name] = true;
|
|
|
|
});
|
|
|
|
|
2017-04-21 07:43:51 +02:00
|
|
|
populate_subscriptions(page_params.subscriptions, true);
|
2017-04-21 07:49:41 +02:00
|
|
|
populate_subscriptions(page_params.unsubscribed, false);
|
2017-04-21 07:53:21 +02:00
|
|
|
populate_subscriptions(page_params.never_subscribed, false);
|
Clean up startup code for streams.
The startup code in subs.js used to intermingle data
stuff and UI stuff in a loop inside a called function,
which made the code hard to reason about.
Now there is a clear separation of concerns, with these methods
being called in succession:
stream_data.initialize_from_page_params();
stream_list.create_initial_sidebar_rows();
The first method was mostly extracted from subs.js, but I simplified
some things, like not needing to make a copy of the hashes
we were passed in, plus I now garbage collect email_dict. Also,
the code path that initialize_from_page_params() mostly replaces
used to call create_sub(), which fired a trigger, but now it
just does data stuff.
Once the data structure is built up, it's a very simple matter
to build the initial sidebar rows, and that's what the second
method does.
2016-10-17 19:34:58 +02:00
|
|
|
|
2017-05-17 03:48:47 +02:00
|
|
|
// Migrate the notifications stream from the new API structure to
|
|
|
|
// what the frontend expects.
|
|
|
|
if (page_params.realm_notifications_stream_id !== -1) {
|
|
|
|
page_params.notifications_stream =
|
|
|
|
exports.get_sub_by_id(page_params.realm_notifications_stream_id).name;
|
|
|
|
} else {
|
|
|
|
page_params.notifications_stream = "";
|
|
|
|
}
|
|
|
|
|
Clean up startup code for streams.
The startup code in subs.js used to intermingle data
stuff and UI stuff in a loop inside a called function,
which made the code hard to reason about.
Now there is a clear separation of concerns, with these methods
being called in succession:
stream_data.initialize_from_page_params();
stream_list.create_initial_sidebar_rows();
The first method was mostly extracted from subs.js, but I simplified
some things, like not needing to make a copy of the hashes
we were passed in, plus I now garbage collect email_dict. Also,
the code path that initialize_from_page_params() mostly replaces
used to call create_sub(), which fired a trigger, but now it
just does data stuff.
Once the data structure is built up, it's a very simple matter
to build the initial sidebar rows, and that's what the second
method does.
2016-10-17 19:34:58 +02:00
|
|
|
// Garbage collect data structures that were only used for initialization.
|
2017-04-21 07:43:51 +02:00
|
|
|
delete page_params.subscriptions;
|
2017-04-21 07:49:41 +02:00
|
|
|
delete page_params.unsubscribed;
|
2017-04-21 07:53:21 +02:00
|
|
|
delete page_params.never_subscribed;
|
Clean up startup code for streams.
The startup code in subs.js used to intermingle data
stuff and UI stuff in a loop inside a called function,
which made the code hard to reason about.
Now there is a clear separation of concerns, with these methods
being called in succession:
stream_data.initialize_from_page_params();
stream_list.create_initial_sidebar_rows();
The first method was mostly extracted from subs.js, but I simplified
some things, like not needing to make a copy of the hashes
we were passed in, plus I now garbage collect email_dict. Also,
the code path that initialize_from_page_params() mostly replaces
used to call create_sub(), which fired a trigger, but now it
just does data stuff.
Once the data structure is built up, it's a very simple matter
to build the initial sidebar rows, and that's what the second
method does.
2016-10-17 19:34:58 +02:00
|
|
|
};
|
|
|
|
|
2017-07-24 15:15:28 +02:00
|
|
|
exports.get_recent_topic_names = function (stream_id) {
|
|
|
|
var topic_objs = recent_topics.get(stream_id);
|
2017-05-14 17:38:07 +02:00
|
|
|
|
2017-07-24 15:15:28 +02:00
|
|
|
if (!topic_objs) {
|
2017-05-14 15:39:02 +02:00
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
2017-07-24 15:15:28 +02:00
|
|
|
return _.map(topic_objs, function (obj) {
|
|
|
|
return obj.name;
|
|
|
|
});
|
2016-10-28 18:47:57 +02:00
|
|
|
};
|
|
|
|
|
2016-10-28 18:26:30 +02:00
|
|
|
exports.populate_stream_topics_for_tests = function (stream_map) {
|
|
|
|
// This is only used by tests.
|
2017-05-14 15:39:02 +02:00
|
|
|
recent_topics = Dict.from(stream_map);
|
2016-10-28 18:26:30 +02:00
|
|
|
};
|
Clean up startup code for streams.
The startup code in subs.js used to intermingle data
stuff and UI stuff in a loop inside a called function,
which made the code hard to reason about.
Now there is a clear separation of concerns, with these methods
being called in succession:
stream_data.initialize_from_page_params();
stream_list.create_initial_sidebar_rows();
The first method was mostly extracted from subs.js, but I simplified
some things, like not needing to make a copy of the hashes
we were passed in, plus I now garbage collect email_dict. Also,
the code path that initialize_from_page_params() mostly replaces
used to call create_sub(), which fired a trigger, but now it
just does data stuff.
Once the data structure is built up, it's a very simple matter
to build the initial sidebar rows, and that's what the second
method does.
2016-10-17 19:34:58 +02:00
|
|
|
|
2017-01-19 00:23:36 +01:00
|
|
|
exports.get_newbie_stream = function () {
|
|
|
|
// This is the stream that we narrow folks to after the tutorial.
|
|
|
|
|
|
|
|
if (exports.is_subscribed("new members")) {
|
|
|
|
return "new members";
|
2017-05-13 20:54:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (exports.notifications_in_home_view()) {
|
2017-01-19 00:23:36 +01:00
|
|
|
return page_params.notifications_stream;
|
|
|
|
}
|
2017-05-13 20:54:53 +02:00
|
|
|
|
2017-01-19 00:23:36 +01:00
|
|
|
return undefined;
|
|
|
|
};
|
|
|
|
|
2017-02-18 20:38:19 +01:00
|
|
|
exports.remove_default_stream = function (stream_id) {
|
|
|
|
page_params.realm_default_streams = _.reject(page_params.realm_default_streams,
|
|
|
|
function (stream) {
|
|
|
|
return stream.stream_id === stream_id;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2013-08-15 21:11:07 +02:00
|
|
|
return exports;
|
|
|
|
|
|
|
|
}());
|
|
|
|
if (typeof module !== 'undefined') {
|
|
|
|
module.exports = stream_data;
|
|
|
|
}
|