diff --git a/static/js/compose.js b/static/js/compose.js index 18562b2e2d..64d2165908 100644 --- a/static/js/compose.js +++ b/static/js/compose.js @@ -563,12 +563,16 @@ exports.has_message_content = function () { // *Synchronously* check if a stream exists. -exports.check_stream_existence = function (stream_name) { +exports.check_stream_existence = function (stream_name, autosubscribe) { var result = "error"; + var request = {'stream': stream_name}; + if (autosubscribe) { + request.autosubscribe = true; + } $.ajax({ type: "POST", url: "/json/subscriptions/exists", - data: {'stream': stream_name}, + data: request, async: false, success: function (data) { if (data.subscribed) { @@ -591,8 +595,8 @@ exports.check_stream_existence = function (stream_name) { // Checks if a stream exists. If not, displays an error and returns // false. -function check_stream_for_send(stream_name) { - var result = exports.check_stream_existence(stream_name); +function check_stream_for_send(stream_name, autosubscribe) { + var result = exports.check_stream_existence(stream_name, autosubscribe); if (result === "error") { compose_error("Error checking subscription", $("#stream")); @@ -621,7 +625,7 @@ function validate_stream_message() { var response; if (!stream_data.is_subscribed(stream_name)) { - switch(check_stream_for_send(stream_name)) { + switch(check_stream_for_send(stream_name, page_params.narrow_stream !== undefined)) { case "does-not-exist": response = "

The stream " + Handlebars.Utils.escapeExpression(stream_name) + " does not exist.

" + diff --git a/static/js/filter.js b/static/js/filter.js index 5491835dd8..4b24d4cb86 100644 --- a/static/js/filter.js +++ b/static/js/filter.js @@ -36,7 +36,9 @@ function mit_edu_topic_name_match(message, operand) { } function message_in_home(message) { - if (message.type === "private" || message.mentioned) { + if (message.type === "private" || message.mentioned || + (page_params.narrow_stream !== undefined && + message.stream.toLowerCase() === page_params.narrow_stream.toLowerCase())) { return true; } @@ -178,12 +180,12 @@ Filter.prototype = { public_operators: function Filter_public_operators() { var safe_to_return = _.filter(this._operators, function (value) { - // Currently just filter out the "in" keyword. - return value[0] !== 'in'; + // Filter out the "in" keyword and the embedded narrow (if any). + return value[0] !== 'in' && !(page_params.narrow_stream !== undefined && + value[0] === "stream" && + value[1].toLowerCase() === page_params.narrow_stream.toLowerCase()); }); - if (safe_to_return.length !== 0) { - return safe_to_return; - } + return safe_to_return; }, operands: function Filter_get_operands(operator) { diff --git a/static/js/narrow.js b/static/js/narrow.js index b1441107ca..ea2fce51b3 100644 --- a/static/js/narrow.js +++ b/static/js/narrow.js @@ -26,7 +26,7 @@ exports.predicate = function () { exports.operators = function () { if (current_filter === undefined) { - return []; + return page_params.narrow; } return current_filter.operators(); }; diff --git a/static/js/zulip.js b/static/js/zulip.js index a8d825a38b..a578c6bf9e 100644 --- a/static/js/zulip.js +++ b/static/js/zulip.js @@ -1126,7 +1126,14 @@ function load_old_messages(opts) { num_after: opts.num_after}; if (opts.msg_list.narrowed && narrow.active()) { - data.narrow = JSON.stringify(narrow.public_operators()); + var operators = narrow.public_operators(); + if (page_params.narrow !== undefined) { + operators = operators.concat(page_params.narrow); + } + data.narrow = JSON.stringify(operators); + } + if (opts.msg_list === home_msg_list && page_params.narrow_stream !== undefined) { + data.narrow = JSON.stringify([["stream", page_params.narrow_stream]]); } $.ajax({ @@ -1295,8 +1302,8 @@ function main() { keepTracking: true}); $(document).on('message_selected.zulip', function (event) { - - if ((event.msg_list === home_msg_list) || (event.msg_list === all_msg_list)) { + // Only advance the pointer when not narrowed + if (event.msg_list === home_msg_list && page_params.narrow_stream === undefined) { if (event.id > furthest_read) { furthest_read = event.id; } diff --git a/zerver/lib/event_queue.py b/zerver/lib/event_queue.py index 4cca55981f..fbd04430cc 100644 --- a/zerver/lib/event_queue.py +++ b/zerver/lib/event_queue.py @@ -288,7 +288,7 @@ def get_client_descriptors_for_realm_all_streams(realm_id): def add_to_client_dicts(client): user_clients.setdefault(client.user_profile_id, []).append(client) - if client.all_public_streams: + if client.all_public_streams or client.narrow != []: realm_clients_all_streams.setdefault(client.realm_id, []).append(client) def allocate_client_descriptor(user_profile_id, realm_id, event_types, client_type, diff --git a/zerver/tests/frontend/node/filter.js b/zerver/tests/frontend/node/filter.js index 19dd69ace7..889de61f0e 100644 --- a/zerver/tests/frontend/node/filter.js +++ b/zerver/tests/frontend/node/filter.js @@ -44,7 +44,7 @@ var Filter = require('js/filter.js'); operators = [['in', 'all']]; filter = new Filter(operators); - assert.deepEqual(filter.public_operators(), undefined); + assert.deepEqual(filter.public_operators(), []); }()); (function test_canonicalizations() { diff --git a/zerver/views/__init__.py b/zerver/views/__init__.py index a3c1cbc16b..6ad157a8d6 100644 --- a/zerver/views/__init__.py +++ b/zerver/views/__init__.py @@ -732,8 +732,19 @@ def home(request): request._email = request.user.email request.client = get_client("website") + narrow = [] + narrow_stream = None + if request.GET.get("narrow"): + try: + narrow_stream = get_stream(request.GET.get("narrow"), user_profile.realm) + assert(narrow_stream is not None) + assert(narrow_stream.is_public()) + narrow = [["stream", narrow_stream.name]] + except Exception: + logging.exception("Narrow parsing") + register_ret = do_events_register(user_profile, request.client, - apply_markdown=True) + apply_markdown=True, narrow=narrow) user_has_messages = (register_ret['max_message_id'] != -1) # Reset our don't-spam-users-with-email counter since the @@ -817,6 +828,18 @@ def home(request): autoscroll_forever = user_profile.autoscroll_forever, show_autoscroll_forever_option = user_profile.realm.domain in ("customer28.invalid", "zulip.com") ) + if narrow_stream is not None: + # In narrow_stream context, initial pointer is just latest message + recipient = get_recipient(Recipient.STREAM, narrow_stream.id) + try: + initial_pointer = Message.objects.filter(recipient=recipient).order_by('id').reverse()[0].id + except IndexError: + initial_pointer = -1 + page_params["narrow_stream"] = narrow_stream.name + page_params["narrow"] = narrow + page_params["max_message_id"] = initial_pointer + page_params["initial_pointer"] = initial_pointer + page_params["have_initial_messages"] = (initial_pointer != -1) statsd.incr('views.home') show_invites = True @@ -1908,16 +1931,19 @@ def json_change_ui_settings(request, user_profile, @authenticated_json_post_view @has_request_variables -def json_stream_exists(request, user_profile, stream=REQ): - return stream_exists_backend(request, user_profile, stream) +def json_stream_exists(request, user_profile, stream=REQ, + autosubscribe=REQ(default=False)): + return stream_exists_backend(request, user_profile, stream, autosubscribe) -def stream_exists_backend(request, user_profile, stream_name): +def stream_exists_backend(request, user_profile, stream_name, autosubscribe): if not valid_stream_name(stream_name): return json_error("Invalid characters in stream name") stream = get_stream(stream_name, user_profile.realm) result = {"exists": bool(stream)} if stream is not None: recipient = get_recipient(Recipient.STREAM, stream.id) + if autosubscribe: + bulk_add_subscriptions([stream], [user_profile]) result["subscribed"] = Subscription.objects.filter(user_profile=user_profile, recipient=recipient, active=True).exists()