mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 14:03:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			282 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			282 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
var reload = (function () {
 | 
						|
 | 
						|
var exports = {};
 | 
						|
 | 
						|
var reload_in_progress = false;
 | 
						|
var reload_pending = false;
 | 
						|
 | 
						|
exports.is_pending = function () {
 | 
						|
    return reload_pending;
 | 
						|
};
 | 
						|
 | 
						|
exports.is_in_progress = function () {
 | 
						|
    return reload_in_progress;
 | 
						|
};
 | 
						|
 | 
						|
function preserve_state(send_after_reload, save_pointer, save_narrow, save_compose) {
 | 
						|
    if (send_after_reload === undefined) {
 | 
						|
        send_after_reload = 0;
 | 
						|
    }
 | 
						|
    var url = "#reload:send_after_reload=" + Number(send_after_reload);
 | 
						|
    url += "+csrf_token=" + encodeURIComponent(csrf_token);
 | 
						|
 | 
						|
    if (save_compose) {
 | 
						|
        if (compose.composing() === 'stream') {
 | 
						|
            url += "+msg_type=stream";
 | 
						|
            url += "+stream=" + encodeURIComponent(compose.stream_name());
 | 
						|
            url += "+subject=" + encodeURIComponent(compose.subject());
 | 
						|
        } else if (compose.composing() === 'private') {
 | 
						|
            url += "+msg_type=private";
 | 
						|
            url += "+recipient=" + encodeURIComponent(compose.recipient());
 | 
						|
        }
 | 
						|
 | 
						|
        if (compose.composing()) {
 | 
						|
            url += "+msg=" + encodeURIComponent(compose.message_content());
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (save_pointer) {
 | 
						|
        var pointer = home_msg_list.selected_id();
 | 
						|
        if (pointer !== -1) {
 | 
						|
            url += "+pointer=" + pointer;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (save_narrow) {
 | 
						|
        var row = home_msg_list.selected_row();
 | 
						|
        if (!narrow.active()) {
 | 
						|
            if (row.length > 0) {
 | 
						|
                url += "+offset=" + row.offset().top;
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            url += "+offset=" + home_msg_list.pre_narrow_offset;
 | 
						|
 | 
						|
            var narrow_pointer = narrowed_msg_list.selected_id();
 | 
						|
            if (narrow_pointer !== -1) {
 | 
						|
                url += "+narrow_pointer=" + narrow_pointer;
 | 
						|
            }
 | 
						|
            var narrow_row = narrowed_msg_list.selected_row();
 | 
						|
            if (narrow_row.length > 0) {
 | 
						|
                url += "+narrow_offset=" + narrow_row.offset().top;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    var oldhash = window.location.hash;
 | 
						|
    if (oldhash.length !== 0 && oldhash[0] === '#') {
 | 
						|
        oldhash = oldhash.slice(1);
 | 
						|
    }
 | 
						|
    url += "+oldhash=" + encodeURIComponent(oldhash);
 | 
						|
 | 
						|
    window.location.replace(url);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Check if we're doing a compose-preserving reload.  This must be
 | 
						|
// done before the first call to get_events
 | 
						|
exports.initialize = function reload__initialize() {
 | 
						|
    var location = window.location.toString();
 | 
						|
    var fragment = location.substring(location.indexOf('#') + 1);
 | 
						|
    if (fragment.search("reload:") !== 0) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    fragment = fragment.replace(/^reload:/, "");
 | 
						|
    var keyvals = fragment.split("+");
 | 
						|
    var vars = {};
 | 
						|
    _.each(keyvals, function (str) {
 | 
						|
        var pair = str.split("=");
 | 
						|
        vars[pair[0]] = decodeURIComponent(pair[1]);
 | 
						|
    });
 | 
						|
 | 
						|
    // Prevent random people on the Internet from constructing links
 | 
						|
    // that make you send a message.
 | 
						|
    if (vars.csrf_token !== csrf_token) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (vars.msg !== undefined) {
 | 
						|
        var send_now = parseInt(vars.send_after_reload, 10);
 | 
						|
 | 
						|
        // TODO: preserve focus
 | 
						|
        compose.start(vars.msg_type, {stream: vars.stream || '',
 | 
						|
                                      subject: vars.subject || '',
 | 
						|
                                      private_message_recipient: vars.recipient || '',
 | 
						|
                                      content: vars.msg || ''});
 | 
						|
        if (send_now) {
 | 
						|
            compose.finish();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    var pointer = parseInt(vars.pointer, 10);
 | 
						|
 | 
						|
    if (pointer) {
 | 
						|
        page_params.orig_initial_pointer = page_params.initial_pointer;
 | 
						|
        page_params.initial_pointer = pointer;
 | 
						|
    }
 | 
						|
    var offset = parseInt(vars.offset, 10);
 | 
						|
    if (offset) {
 | 
						|
        page_params.initial_offset = offset;
 | 
						|
    }
 | 
						|
 | 
						|
    var narrow_pointer = parseInt(vars.narrow_pointer, 10);
 | 
						|
    if (narrow_pointer) {
 | 
						|
        page_params.initial_narrow_pointer = narrow_pointer;
 | 
						|
    }
 | 
						|
    var narrow_offset = parseInt(vars.narrow_offset, 10);
 | 
						|
    if (narrow_offset) {
 | 
						|
        page_params.initial_narrow_offset = narrow_offset;
 | 
						|
    }
 | 
						|
 | 
						|
    activity.new_user_input = false;
 | 
						|
    hashchange.changehash(vars.oldhash);
 | 
						|
};
 | 
						|
 | 
						|
function clear_message_list(msg_list) {
 | 
						|
    if (!msg_list) { return; }
 | 
						|
    msg_list.clear();
 | 
						|
    // Some pending ajax calls may still be processed and they to not expect an
 | 
						|
    // empty msg_list.
 | 
						|
    msg_list._items = [{id: 1}];
 | 
						|
}
 | 
						|
 | 
						|
function cleanup_before_reload() {
 | 
						|
    try {
 | 
						|
        // Unbind all the jQuery event listeners
 | 
						|
        $('*').off();
 | 
						|
 | 
						|
        // Abort all pending ajax requests`
 | 
						|
        channel.abort_all();
 | 
						|
 | 
						|
        // Free all the DOM in the main_div
 | 
						|
        $("#main_div").empty();
 | 
						|
 | 
						|
        // Now that the DOM is empty our beforeunload callback has been
 | 
						|
        // removed.
 | 
						|
        server_events.cleanup_event_queue();
 | 
						|
 | 
						|
        // Empty the large collections
 | 
						|
        clear_message_list(all_msg_list);
 | 
						|
        clear_message_list(home_msg_list);
 | 
						|
        clear_message_list(narrowed_msg_list);
 | 
						|
        message_store.clear();
 | 
						|
 | 
						|
    } catch (ex) {
 | 
						|
        blueslip.error('Failed to cleanup before reloading',
 | 
						|
                       undefined, ex.stack);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
function do_reload_app(send_after_reload, save_pointer, save_narrow, save_compose, message) {
 | 
						|
    if (reload_in_progress) { return; }
 | 
						|
 | 
						|
    // TODO: we should completely disable the UI here
 | 
						|
    if (save_pointer || save_narrow || save_compose) {
 | 
						|
        preserve_state(send_after_reload, save_pointer, save_narrow, save_compose);
 | 
						|
    }
 | 
						|
 | 
						|
    if (message === undefined) {
 | 
						|
        message = "Reloading";
 | 
						|
    }
 | 
						|
 | 
						|
    // TODO: We need a better API for showing messages.
 | 
						|
    ui.report_message(message, $("#reloading-application"));
 | 
						|
    blueslip.log('Starting server requested page reload');
 | 
						|
    reload_in_progress = true;
 | 
						|
 | 
						|
    if (feature_flags.cleanup_before_reload) {
 | 
						|
        cleanup_before_reload();
 | 
						|
    }
 | 
						|
 | 
						|
    window.location.reload(true);
 | 
						|
}
 | 
						|
 | 
						|
exports.initiate = function (options) {
 | 
						|
    options = _.defaults({}, options, {
 | 
						|
        immediate: false,
 | 
						|
        save_pointer: true,
 | 
						|
        save_narrow: true,
 | 
						|
        save_compose: true,
 | 
						|
        send_after_reload: false
 | 
						|
    });
 | 
						|
 | 
						|
    if (options.save_pointer === undefined ||
 | 
						|
        options.save_narrow === undefined ||
 | 
						|
        options.save_compose === undefined) {
 | 
						|
        blueslip.error("reload.initiate() called without explicit save options.");
 | 
						|
    }
 | 
						|
 | 
						|
    if (options.immediate) {
 | 
						|
        do_reload_app(options.send_after_reload,
 | 
						|
                      options.save_pointer,
 | 
						|
                      options.save_narrow,
 | 
						|
                      options.save_compose,
 | 
						|
                      options.message);
 | 
						|
    }
 | 
						|
 | 
						|
    if (reload_pending) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    reload_pending = true;
 | 
						|
 | 
						|
    // If the user is composing a message, reload if they become idle
 | 
						|
    // while composing.  If they finish or cancel the compose, wait
 | 
						|
    // until they're idle again
 | 
						|
    var idle_control;
 | 
						|
    var unconditional_timeout = 1000*60*30 + util.random_int(0, 1000*60*5);
 | 
						|
    var composing_timeout     = 1000*60*5  + util.random_int(0, 1000*60);
 | 
						|
    var home_timeout          = 1000*60    + util.random_int(0, 1000*60);
 | 
						|
    var compose_done_handler, compose_started_handler;
 | 
						|
 | 
						|
    function reload_from_idle () {
 | 
						|
        do_reload_app(false,
 | 
						|
                      options.save_pointer,
 | 
						|
                      options.save_narrow,
 | 
						|
                      options.save_compose,
 | 
						|
                      options.message);
 | 
						|
    }
 | 
						|
 | 
						|
    // Make sure we always do a reload eventually
 | 
						|
    setTimeout(reload_from_idle, unconditional_timeout);
 | 
						|
 | 
						|
    compose_done_handler = function () {
 | 
						|
        idle_control.cancel();
 | 
						|
        idle_control = $(document).idle({'idle': home_timeout,
 | 
						|
                                         'onIdle': reload_from_idle});
 | 
						|
        $(document).off('compose_canceled.zulip compose_finished.zulip',
 | 
						|
                        compose_done_handler);
 | 
						|
        $(document).on('compose_started.zulip', compose_started_handler);
 | 
						|
    };
 | 
						|
    compose_started_handler = function () {
 | 
						|
        idle_control.cancel();
 | 
						|
        idle_control = $(document).idle({'idle': composing_timeout,
 | 
						|
                                         'onIdle': reload_from_idle});
 | 
						|
        $(document).off('compose_started.zulip', compose_started_handler);
 | 
						|
        $(document).on('compose_canceled.zulip compose_finished.zulip',
 | 
						|
                       compose_done_handler);
 | 
						|
    };
 | 
						|
 | 
						|
    if (compose.composing()) {
 | 
						|
        idle_control = $(document).idle({'idle': composing_timeout,
 | 
						|
                                         'onIdle': reload_from_idle});
 | 
						|
        $(document).on('compose_canceled.zulip compose_finished.zulip',
 | 
						|
                       compose_done_handler);
 | 
						|
    } else {
 | 
						|
        idle_control = $(document).idle({'idle': home_timeout,
 | 
						|
                                         'onIdle': reload_from_idle});
 | 
						|
        $(document).on('compose_started.zulip', compose_started_handler);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
window.addEventListener('beforeunload', function () {
 | 
						|
    // When navigating away from the page do not try to reload.
 | 
						|
    // The polling get_events call will fail after we delete the event queue.
 | 
						|
    // When that happens we reload the page to correct the problem. If this
 | 
						|
    // happens before the navigation is complete the user is kept captive at
 | 
						|
    // zulip.
 | 
						|
    reload_in_progress = true;
 | 
						|
});
 | 
						|
 | 
						|
 | 
						|
return exports;
 | 
						|
}());
 |