mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 14:03:30 +00:00 
			
		
		
		
	This commit was originally automatically generated using `tools/lint --only=eslint --fix`. It was then modified by tabbott to contain only changes to a set of files that are unlikely to result in significant merge conflicts with any open pull request, excluding about 20 files. His plan is to merge the remaining changes with more precise care, potentially involving merging parts of conflicting pull requests before running the `eslint --fix` operation. Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
		
			
				
	
	
		
			173 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			173 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
// This module just manages data.  See activity.js for
 | 
						|
// the UI of our buddy list.
 | 
						|
 | 
						|
exports.presence_info = {};
 | 
						|
 | 
						|
 | 
						|
/* Mark users as offline after 140 seconds since their last checkin,
 | 
						|
 * Keep in sync with zerver/tornado/event_queue.py:receiver_is_idle
 | 
						|
 */
 | 
						|
const OFFLINE_THRESHOLD_SECS = 140;
 | 
						|
 | 
						|
const BIG_REALM_COUNT = 250;
 | 
						|
 | 
						|
const MOBILE_DEVICES = ["Android", "ZulipiOS", "ios"];
 | 
						|
 | 
						|
function is_mobile(device) {
 | 
						|
    return MOBILE_DEVICES.indexOf(device) !== -1;
 | 
						|
}
 | 
						|
 | 
						|
exports.is_active = function (user_id) {
 | 
						|
    if (exports.presence_info[user_id]) {
 | 
						|
        const status = exports.presence_info[user_id].status;
 | 
						|
        if (status && status === "active") {
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
};
 | 
						|
 | 
						|
exports.get_status = function (user_id) {
 | 
						|
    if (people.is_my_user_id(user_id)) {
 | 
						|
        return "active";
 | 
						|
    }
 | 
						|
    if (user_id in exports.presence_info) {
 | 
						|
        return exports.presence_info[user_id].status;
 | 
						|
    }
 | 
						|
    return "offline";
 | 
						|
};
 | 
						|
 | 
						|
exports.get_user_ids = function () {
 | 
						|
    const user_ids = Object.keys(exports.presence_info);
 | 
						|
    return user_ids;
 | 
						|
};
 | 
						|
 | 
						|
function status_from_timestamp(baseline_time, info) {
 | 
						|
    let status = 'offline';
 | 
						|
    let last_active = 0;
 | 
						|
    let mobileAvailable = false;
 | 
						|
    let nonmobileAvailable = false;
 | 
						|
    _.each(info, function (device_presence, device) {
 | 
						|
        const age = baseline_time - device_presence.timestamp;
 | 
						|
        if (last_active < device_presence.timestamp) {
 | 
						|
            last_active = device_presence.timestamp;
 | 
						|
        }
 | 
						|
        if (is_mobile(device)) {
 | 
						|
            mobileAvailable = device_presence.pushable || mobileAvailable;
 | 
						|
        }
 | 
						|
        if (age < OFFLINE_THRESHOLD_SECS) {
 | 
						|
            switch (device_presence.status) {
 | 
						|
            case 'active':
 | 
						|
                if (is_mobile(device)) {
 | 
						|
                    mobileAvailable = true;
 | 
						|
                } else {
 | 
						|
                    nonmobileAvailable = true;
 | 
						|
                }
 | 
						|
                status = device_presence.status;
 | 
						|
                break;
 | 
						|
            case 'idle':
 | 
						|
                if (status !== 'active') {
 | 
						|
                    status = device_presence.status;
 | 
						|
                }
 | 
						|
                break;
 | 
						|
            case 'offline':
 | 
						|
                if (status !== 'active' && status !== 'idle') {
 | 
						|
                    status = device_presence.status;
 | 
						|
                }
 | 
						|
                break;
 | 
						|
            default:
 | 
						|
                blueslip.error('Unexpected status', {presence_object: device_presence, device: device}, undefined);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    });
 | 
						|
    return {status: status,
 | 
						|
            mobile: !nonmobileAvailable && mobileAvailable,
 | 
						|
            last_active: last_active };
 | 
						|
}
 | 
						|
 | 
						|
// For testing
 | 
						|
exports._status_from_timestamp = status_from_timestamp;
 | 
						|
 | 
						|
exports.set_info_for_user = function (user_id, info, server_time) {
 | 
						|
    const status = status_from_timestamp(server_time, info);
 | 
						|
    exports.presence_info[user_id] = status;
 | 
						|
};
 | 
						|
 | 
						|
exports.set_info = function (presences, server_timestamp) {
 | 
						|
    exports.presence_info = {};
 | 
						|
    _.each(presences, function (info, this_email) {
 | 
						|
        const person = people.get_by_email(this_email);
 | 
						|
 | 
						|
        if (person === undefined) {
 | 
						|
            if (!(server_events.suspect_offline || reload_state.is_in_progress())) {
 | 
						|
                // If we're online, and we get a user who we don't
 | 
						|
                // know about in the presence data, throw an error.
 | 
						|
                blueslip.error('Unknown email in presence data: ' + this_email);
 | 
						|
            }
 | 
						|
            // Either way, we deal by skipping this user and
 | 
						|
            // rendering everyone else, to avoid disruption.
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        const user_id = person.user_id;
 | 
						|
 | 
						|
        if (user_id) {
 | 
						|
            const status = status_from_timestamp(server_timestamp,
 | 
						|
                                                 info);
 | 
						|
            exports.presence_info[user_id] = status;
 | 
						|
        }
 | 
						|
    });
 | 
						|
    exports.update_info_for_small_realm();
 | 
						|
};
 | 
						|
 | 
						|
exports.update_info_for_small_realm = function () {
 | 
						|
    if (people.get_realm_count() >= BIG_REALM_COUNT) {
 | 
						|
        // For big realms, we don't want to bloat our buddy
 | 
						|
        // lists with lots of long-time-inactive users.
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    // For small realms, we create presence info for users
 | 
						|
    // that the server didn't include in its presence update.
 | 
						|
    const persons = people.get_realm_persons();
 | 
						|
 | 
						|
    _.each(persons, function (person) {
 | 
						|
        const user_id = person.user_id;
 | 
						|
        let status = "offline";
 | 
						|
 | 
						|
        if (exports.presence_info[user_id]) {
 | 
						|
            // this is normal, we have data for active
 | 
						|
            // users that we don't want to clobber.
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        if (person.is_bot) {
 | 
						|
            // we don't show presence for bots
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        if (people.is_my_user_id(user_id)) {
 | 
						|
            status = "active";
 | 
						|
        }
 | 
						|
 | 
						|
        exports.presence_info[user_id] = {
 | 
						|
            status: status,
 | 
						|
            mobile: false,
 | 
						|
            last_active: undefined,
 | 
						|
        };
 | 
						|
    });
 | 
						|
};
 | 
						|
 | 
						|
exports.last_active_date = function (user_id) {
 | 
						|
    const info = exports.presence_info[user_id];
 | 
						|
 | 
						|
    if (!info || !info.last_active) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    const date = new XDate(info.last_active * 1000);
 | 
						|
    return date;
 | 
						|
};
 | 
						|
 | 
						|
window.presence = exports;
 |