<commit_before>var message_array = [];
var message_dict = {};
var subject_dict = {};
var people_hash = {};

var selected_message_class = 'selected_message';
var viewport = $(window);
var reloading_app = false;

var selected_message_id = -1;  /* to be filled in on document.ready */
var selected_message;  // = rows.get(selected_message_id)
var get_updates_params = {
    first: -1,
    last:  -1,
    failures: 0,
    server_generation: -1, /* to be filled in on document.ready */
    reload_pending: 0
};

$(function () {
    var i;
    var send_status = $('#send-status');
    var buttons = $('#compose').find('input[type="submit"]');

    var options = {
        dataType: 'json', // This seems to be ignored. We still get back an xhr.
        beforeSubmit: compose.validate,
        success: function (resp, statusText, xhr, form) {
            form.find('textarea').val('');
            send_status.hide();
            compose.hide();
            buttons.removeAttr('disabled');
            start_reload_app();
        },
        error: function (xhr, error_type) {
            if (error_type !== 'timeout' && get_updates_params.reload_pending) {
                // The error might be due to the server changing
                do_reload_app_preserving_compose(true);
                return;
            }
            var response = "Error sending message";
            if (xhr.status.toString().charAt(0) === "4") {
                // Only display the error response for 4XX, where we've crafted
                // a nice response.
                response += ": " + $.parseJSON(xhr.responseText).msg;
            }
            send_status.removeClass(status_classes)
                       .addClass('alert-error')
                       .text(response)
                       .append($('<span />')
                           .addClass('send-status-close').html('&times;')
                           .click(function () { send_status.stop(true).fadeOut(500); }))
                       .stop(true).fadeTo(0,1);

            buttons.removeAttr('disabled');
        }
    };

    send_status.hide();
    $("#compose form").ajaxForm(options);

    $.each(people_list, function (idx, person) {
        people_hash[person.email] = 1;
    });
});

// The "message groups", i.e. blocks of messages collapsed by recipient.
// Each message table has a list of lists.
var message_groups = {
    zhome: [],
    zfilt: []
};

// Why do we look at the 'bottom' in above_view_threshold and the top
// in below_view_threshold as opposed to vice versa?  Mostly to handle
// the case of gigantic messages.  Imagine the case of a selected
// message that's so big that it takes up an two entire screens. The
// selector shouldn't move away from it until after the *bottom* of
// the message has gone too high up on the screen.  (Otherwise we'd
// move the pointer right after part of the first screenful.)
function above_view_threshold(message, useTop) {
    // Barnowl-style thresholds: the bottom of the pointer is never
    // above the 1/5 mark.
    // (if useTop = true, we look at the top of the pointer instead)
    var position = message.offset().top;
    if (!useTop) {
        position += message.outerHeight(true);
    }
    return position < viewport.scrollTop() + viewport.height() / 5;
}

function below_view_threshold(message) {
    // Barnowl-style thresholds: the top of the pointer is never below
    // the 2/3-mark.
    return message.offset().top > viewport.scrollTop() + viewport.height() * 2 / 3;
}

function recenter_view(message) {
    // Barnowl-style recentering: if the pointer is too high, center
    // in the middle of the screen. If the pointer is too low, center
    // on the 1/5-mark.

    // If this logic changes, above_view_threshold andd
    // below_view_threshold must also change.
    if (above_view_threshold(message, true)) {
        // We specifically say useTop=true here, because suppose you're using
        // the arrow keys to arrow up and you've moved up to a huge message.
        // The message is so big that the bottom part of makes it not
        // "above the view threshold". But since we're using the arrow keys
        // to get here, the reason we selected this message is because
        // we want to read it; so here we care about the top part.
        viewport.scrollTop(selected_message.offset().top - viewport.height() / 2);
    } else if (below_view_threshold(message)) {
        viewport.scrollTop(selected_message.offset().top - viewport.height() / 5);
    }
}

function scroll_to_selected() {
    recenter_view(selected_message);
}

function get_huddle_recipient(message) {
    var recipient, i;
    var other_recipients = $.grep(message.display_recipient,
                                  function (element, index) {
                                      return element.email !== email;
                                  });
    if (other_recipients.length === 0) {
        // huddle with oneself
        return message.display_recipient[0].email;
    }

    recipient = other_recipients[0].email;
    for (i = 1; i < other_recipients.length; i++) {
        recipient += ', ' + other_recipients[i].email;
    }
    return recipient;
}

function get_huddle_recipient_names(message) {
    var recipient, i;
    var other_recipients = $.grep(message.display_recipient,
                                  function (element, index) {
                                      return element.email !== email;
                                  });
    if (other_recipients.length === 0) {
        // huddle with oneself
        return message.display_recipient[0].full_name;
    }

    recipient = other_recipients[0].full_name;
    for (i = 1; i < other_recipients.length; i++) {
        recipient += ', ' + other_recipients[i].full_name;
    }
    return recipient;
}

function respond_to_message(reply_type) {
    var message, msg_type;
    message = message_dict[selected_message_id];

    var stream = '';
    var subject = '';
    if (message.type === "stream") {
        stream = message.display_recipient;
        subject = message.subject;
    }

    var huddle_recipient = message.reply_to;
    if (reply_type === "personal" && message.type === "huddle") {
        // reply_to for huddle messages is the whole huddle, so for
        // personals replies we need to set the the huddle recipient
        // to just the sender
        huddle_recipient = message.sender_email;
    }
    msg_type = reply_type;
    if (msg_type === undefined) {
        msg_type = message.type;
    }
    if (msg_type === "huddle") {
        // Huddle messages use the personals compose box
        msg_type = "personal";
    }
    compose.show(msg_type, {'stream': stream, 'subject': subject,
                            'huddle_recipient': huddle_recipient});
}

// Called by mouseover etc.
function select_message_by_id(message_id) {
    if (message_id === selected_message_id) {
        return;
    }
    select_message(rows.get(message_id), false);
}

// Called on page load and when we [un]narrow.
// Forces a call to select_message even if the id has not changed,
// because the visible table might have.
function select_and_show_by_id(message_id) {
    select_message(rows.get(message_id), true);
}

function update_selected_message(message) {
    $('.' + selected_message_class).removeClass(selected_message_class);
    message.addClass(selected_message_class);

    var new_selected_id = rows.id(message);
    if (!narrow.active() && new_selected_id !== selected_message_id) {
        // Narrowing is a temporary view on top of the home view and
        // doesn't permanently affect where you are.<commit_msg>Fix responding to messages (broken by rebase error)<commit_after>var message_array = [];
var message_dict = {};
var subject_dict = {};
var people_hash = {};

var selected_message_class = 'selected_message';
var viewport = $(window);
var reloading_app = false;

var selected_message_id = -1;  /* to be filled in on document.ready */
var selected_message;  // = rows.get(selected_message_id)
var get_updates_params = {
    first: -1,
    last:  -1,
    failures: 0,
    server_generation: -1, /* to be filled in on document.ready */
    reload_pending: 0
};

$(function () {
    var i;
    var send_status = $('#send-status');
    var buttons = $('#compose').find('input[type="submit"]');

    var options = {
        dataType: 'json', // This seems to be ignored. We still get back an xhr.
        beforeSubmit: compose.validate,
        success: function (resp, statusText, xhr, form) {
            form.find('textarea').val('');
            send_status.hide();
            compose.hide();
            buttons.removeAttr('disabled');
            start_reload_app();
        },
        error: function (xhr, error_type) {
            if (error_type !== 'timeout' && get_updates_params.reload_pending) {
                // The error might be due to the server changing
                do_reload_app_preserving_compose(true);
                return;
            }
            var response = "Error sending message";
            if (xhr.status.toString().charAt(0) === "4") {
                // Only display the error response for 4XX, where we've crafted
                // a nice response.
                response += ": " + $.parseJSON(xhr.responseText).msg;
            }
            send_status.removeClass(status_classes)
                       .addClass('alert-error')
                       .text(response)
                       .append($('<span />')
                           .addClass('send-status-close').html('&times;')
                           .click(function () { send_status.stop(true).fadeOut(500); }))
                       .stop(true).fadeTo(0,1);

            buttons.removeAttr('disabled');
        }
    };

    send_status.hide();
    $("#compose form").ajaxForm(options);

    $.each(people_list, function (idx, person) {
        people_hash[person.email] = 1;
    });
});

// The "message groups", i.e. blocks of messages collapsed by recipient.
// Each message table has a list of lists.
var message_groups = {
    zhome: [],
    zfilt: []
};

// Why do we look at the 'bottom' in above_view_threshold and the top
// in below_view_threshold as opposed to vice versa?  Mostly to handle
// the case of gigantic messages.  Imagine the case of a selected
// message that's so big that it takes up an two entire screens. The
// selector shouldn't move away from it until after the *bottom* of
// the message has gone too high up on the screen.  (Otherwise we'd
// move the pointer right after part of the first screenful.)
function above_view_threshold(message, useTop) {
    // Barnowl-style thresholds: the bottom of the pointer is never
    // above the 1/5 mark.
    // (if useTop = true, we look at the top of the pointer instead)
    var position = message.offset().top;
    if (!useTop) {
        position += message.outerHeight(true);
    }
    return position < viewport.scrollTop() + viewport.height() / 5;
}

function below_view_threshold(message) {
    // Barnowl-style thresholds: the top of the pointer is never below
    // the 2/3-mark.
    return message.offset().top > viewport.scrollTop() + viewport.height() * 2 / 3;
}

function recenter_view(message) {
    // Barnowl-style recentering: if the pointer is too high, center
    // in the middle of the screen. If the pointer is too low, center
    // on the 1/5-mark.

    // If this logic changes, above_view_threshold andd
    // below_view_threshold must also change.
    if (above_view_threshold(message, true)) {
        // We specifically say useTop=true here, because suppose you're using
        // the arrow keys to arrow up and you've moved up to a huge message.
        // The message is so big that the bottom part of makes it not
        // "above the view threshold". But since we're using the arrow keys
        // to get here, the reason we selected this message is because
        // we want to read it; so here we care about the top part.
        viewport.scrollTop(selected_message.offset().top - viewport.height() / 2);
    } else if (below_view_threshold(message)) {
        viewport.scrollTop(selected_message.offset().top - viewport.height() / 5);
    }
}

function scroll_to_selected() {
    recenter_view(selected_message);
}

function get_huddle_recipient(message) {
    var recipient, i;
    var other_recipients = $.grep(message.display_recipient,
                                  function (element, index) {
                                      return element.email !== email;
                                  });
    if (other_recipients.length === 0) {
        // huddle with oneself
        return message.display_recipient[0].email;
    }

    recipient = other_recipients[0].email;
    for (i = 1; i < other_recipients.length; i++) {
        recipient += ', ' + other_recipients[i].email;
    }
    return recipient;
}

function get_huddle_recipient_names(message) {
    var recipient, i;
    var other_recipients = $.grep(message.display_recipient,
                                  function (element, index) {
                                      return element.email !== email;
                                  });
    if (other_recipients.length === 0) {
        // huddle with oneself
        return message.display_recipient[0].full_name;
    }

    recipient = other_recipients[0].full_name;
    for (i = 1; i < other_recipients.length; i++) {
        recipient += ', ' + other_recipients[i].full_name;
    }
    return recipient;
}

function respond_to_message(reply_type) {
    var message, msg_type;
    message = message_dict[selected_message_id];

    var stream = '';
    var subject = '';
    if (message.type === "stream") {
        stream = message.display_recipient;
        subject = message.subject;
    }

    var huddle_recipient = message.reply_to;
    if (reply_type === "personal" && message.type === "huddle") {
        // reply_to for huddle messages is the whole huddle, so for
        // personals replies we need to set the the huddle recipient
        // to just the sender
        huddle_recipient = message.sender_email;
    }
    msg_type = reply_type;
    if (msg_type === undefined) {
        msg_type = message.type;
    }
    if (msg_type === "huddle") {
        // Huddle messages use the personals compose box
        msg_type = "personal";
    }
    compose.start(msg_type, {'stream': stream, 'subject': subject,
                             'huddle_recipient': huddle_recipient});
}

// Called by mouseover etc.
function select_message_by_id(message_id) {
    if (message_id === selected_message_id) {
        return;
    }
    select_message(rows.get(message_id), false);
}

// Called on page load and when we [un]narrow.
// Forces a call to select_message even if the id has not changed,
// because the visible table might have.
function select_and_show_by_id(message_id) {
    select_message(rows.get(message_id), true);
}

function update_selected_message(message) {
    $('.' + selected_message_class).removeClass(selected_message_class);
    message.addClass(selected_message_class);

    var new_selected_id = rows.id(message);
    if (!narrow.active() && new_selected_id !== selected_message_id) {
        // Narrowing is a temporary view on top of the home view and
        // doesn't permanently affect where you are.
{'fraction_non_alphanumeric': 0.11176240719030871, 'fraction_numerical': 0.004428813338543702, 'mean_word_length': 2.3475038151297145, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5972286', 'n_tokens_mistral': 4507, 'n_tokens_neox': 4292, 'n_words': 1296}