Browse Source

Single instance checks

master
Igor Zhukov 10 years ago
parent
commit
a09191b65f
  1. 2
      app/js/lib/config.js
  2. 22
      app/js/lib/mtproto.js
  3. 81
      app/js/lib/mtproto_wrapper.js
  4. 5
      app/js/lib/ng_utils.js
  5. 3
      app/js/locales/en-us.json
  6. 2
      app/js/services.js
  7. 3
      app/partials/desktop/error_modal.html

2
app/js/lib/config.js

@ -133,7 +133,7 @@ Config.LangCountries = {"es": "ES", "ru": "RU", "en": "US", "de": "DE", "it": "I
for (i = 0; i < keys.length; i++) { for (i = 0; i < keys.length; i++) {
key = keys[i] = prefix + keys[i]; key = keys[i] = prefix + keys[i];
if (cache[key] !== undefined) { if (key.substr(0, 3) != 'xt_' && cache[key] !== undefined) {
result.push(cache[key]); result.push(cache[key]);
} }
else if (useLs) { else if (useLs) {

22
app/js/lib/mtproto.js

@ -563,6 +563,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
iii = 0, iii = 0,
offline, offline,
offlineInited = false, offlineInited = false,
akStopped = false,
chromeMatches = navigator.userAgent.match(/Chrome\/(\d+(\.\d+)?)/), chromeMatches = navigator.userAgent.match(/Chrome\/(\d+(\.\d+)?)/),
chromeVersion = chromeMatches && parseFloat(chromeMatches[1]) || false, chromeVersion = chromeMatches && parseFloat(chromeMatches[1]) || false,
xhrSendBuffer = !('ArrayBufferView' in window) && (!chromeVersion || chromeVersion < 30); xhrSendBuffer = !('ArrayBufferView' in window) && (!chromeVersion || chromeVersion < 30);
@ -771,7 +772,9 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
MtpNetworker.prototype.checkLongPoll = function(force) { MtpNetworker.prototype.checkLongPoll = function(force) {
var isClean = this.cleanupSent(); var isClean = this.cleanupSent();
// console.log('Check lp', this.longPollPending, tsNow(), this.dcID, isClean); // console.log('Check lp', this.longPollPending, tsNow(), this.dcID, isClean);
if (this.longPollPending && tsNow() < this.longPollPending || this.offline) { if (this.longPollPending && tsNow() < this.longPollPending ||
this.offline ||
akStopped) {
return false; return false;
} }
var self = this; var self = this;
@ -962,7 +965,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
MtpNetworker.prototype.performSheduledRequest = function() { MtpNetworker.prototype.performSheduledRequest = function() {
// console.log(dT(), 'sheduled', this.dcID, this.iii); // console.log(dT(), 'sheduled', this.dcID, this.iii);
if (this.offline) { if (this.offline || akStopped) {
console.log(dT(), 'Cancel sheduled'); console.log(dT(), 'Cancel sheduled');
return false; return false;
} }
@ -1558,13 +1561,26 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
} }
}; };
function startAll() {
if (akStopped) {
akStopped = false;
updatesProcessor({_: 'new_session_created'});
}
}
function stopAll() {
akStopped = true;
}
return { return {
getNetworker: function (dcID, authKey, serverSalt, options) { getNetworker: function (dcID, authKey, serverSalt, options) {
return new MtpNetworker(dcID, authKey, serverSalt, options); return new MtpNetworker(dcID, authKey, serverSalt, options);
}, },
setUpdatesProcessor: function (callback) { setUpdatesProcessor: function (callback) {
updatesProcessor = callback; updatesProcessor = callback;
} },
stopAll: stopAll,
startAll: startAll
}; };
}) })

81
app/js/lib/mtproto_wrapper.js

@ -7,12 +7,14 @@
angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto']) angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
.factory('MtpApiManager', function (Storage, MtpAuthorizer, MtpNetworkerFactory, ErrorService, $q) { .factory('MtpApiManager', function (Storage, MtpAuthorizer, MtpNetworkerFactory, MtpSingleInstanceService, ErrorService, $q) {
var cachedNetworkers = {}, var cachedNetworkers = {},
cachedUploadNetworkers = {}, cachedUploadNetworkers = {},
cachedExportPromise = {}, cachedExportPromise = {},
baseDcID = false; baseDcID = false;
MtpSingleInstanceService.start();
Storage.get('dc').then(function (dcID) { Storage.get('dc').then(function (dcID) {
if (dcID) { if (dcID) {
baseDcID = dcID; baseDcID = dcID;
@ -610,3 +612,80 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
uploadFile: uploadFile uploadFile: uploadFile
}; };
}) })
.service('MtpSingleInstanceService', function ($rootScope, $interval, Storage, AppRuntimeManager, IdleManager, ErrorService, MtpNetworkerFactory) {
var instanceID = nextRandomInt(0xFFFFFFFF);
var started = false;
var masterInstance = false;
var startTime = tsNow();
var errorShowTime = 0;
function start() {
if (!started) {
started = true;
IdleManager.start();
startTime = tsNow();
$rootScope.$watch('idle.isIDLE', checkInstance);
$interval(checkInstance, 5000);
checkInstance();
try {
$($window).on('beforeunload', clearInstance);
} catch (e) {};
}
}
function clearInstance () {
Storage.remove(masterInstance ? 'xt_instance' : 'xt_idle_instance');
}
function checkInstance() {
var time = tsNow();
var idle = $rootScope.idle && $rootScope.idle.isIDLE;
var newInstance = {id: instanceID, idle: idle, time: time};
Storage.get('xt_instance', 'xt_idle_instance').then(function (result) {
var curInstance = result[0],
idleInstance = result[1];
if (!curInstance ||
curInstance.time < time - 60000 ||
curInstance.id == instanceID ||
curInstance.idle ||
!idle) {
if (idleInstance) {
if (idleInstance.id == instanceID) {
Storage.remove('xt_idle_instance');
}
else if (idleInstance.time > time - 10000 &&
time > errorShowTime) {
ErrorService.show({error: {type: 'MULTIPLE_TABS_OPEN'}});
errorShowTime += tsNow() + 60000;
}
}
Storage.set({xt_instance: newInstance});
if (!masterInstance) {
MtpNetworkerFactory.startAll();
}
masterInstance = true;
} else {
Storage.set({xt_idle_instance: newInstance});
if (masterInstance) {
MtpNetworkerFactory.stopAll();
}
masterInstance = false;
}
});
}
return {
start: start
}
})

5
app/js/lib/ng_utils.js

@ -808,6 +808,11 @@ angular.module('izhukov.utils', [])
chrome.runtime.reload(); chrome.runtime.reload();
}; };
}, },
close: function () {
try {
$window.close();
} catch (e) {}
},
focus: function () { focus: function () {
if (window.navigator.mozApps && document.hidden) { if (window.navigator.mozApps && document.hidden) {
// Get app instance and launch it to bring app to foreground // Get app instance and launch it to bring app to foreground

3
app/js/locales/en-us.json

@ -195,6 +195,7 @@
"message_service_left_group": "left group", "message_service_left_group": "left group",
"message_service_unsupported_action": "Unsupported action {action}", "message_service_unsupported_action": "Unsupported action {action}",
"error_modal_warning_title": "Warning",
"error_modal_bad_request_title": "Error", "error_modal_bad_request_title": "Error",
"error_modal_unauthorized_title": "Unauthorized", "error_modal_unauthorized_title": "Unauthorized",
"error_modal_forbidden_title": "Access denied", "error_modal_forbidden_title": "Access denied",
@ -224,6 +225,8 @@
"error_modal_flood_description": "You are performing too many actions. Please try again later.", "error_modal_flood_description": "You are performing too many actions. Please try again later.",
"error_modal_internal_description": "Internal server error occured. Please try again later.", "error_modal_internal_description": "Internal server error occured. Please try again later.",
"error_modal_tech_details": "Technical details here", "error_modal_tech_details": "Technical details here",
"error_modal_multiple_open_tabs": "Telegram Web doesn't support working in multiple tabs. Please close other app instances.",
"head_new_group": "New Group", "head_new_group": "New Group",
"head_new_contact": "New Contact", "head_new_contact": "New Contact",

2
app/js/services.js

@ -3463,7 +3463,9 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
try { try {
if ('onbeforeunload' in window) {
$($window).on('beforeunload', notificationsClear); $($window).on('beforeunload', notificationsClear);
}
} catch (e) {} } catch (e) {}
} }

3
app/partials/desktop/error_modal.html

@ -5,6 +5,7 @@
<div class="modal-body"> <div class="modal-body">
<h4 ng-if="error" class="modal_simple_header" ng-switch="error.type"> <h4 ng-if="error" class="modal_simple_header" ng-switch="error.type">
<span ng-switch-when="MULTIPLE_TABS_OPEN" my-i18n="error_modal_warning_title"></span>
<span ng-switch-default ng-switch="error.code"> <span ng-switch-default ng-switch="error.code">
<span ng-switch-when="400" my-i18n="error_modal_bad_request_title"></span> <span ng-switch-when="400" my-i18n="error_modal_bad_request_title"></span>
<span ng-switch-when="401" my-i18n="error_modal_unauthorized_title"></span> <span ng-switch-when="401" my-i18n="error_modal_unauthorized_title"></span>
@ -35,6 +36,8 @@
<span ng-switch-when="PHONEBOOK_GET_CONTACTS_FAILED" my-i18n="error_modal_phonebook_required_description"></span> <span ng-switch-when="PHONEBOOK_GET_CONTACTS_FAILED" my-i18n="error_modal_phonebook_required_description"></span>
<span ng-switch-when="USERNAME_INVALID" my-i18n="error_modal_username_invalid_description"></span> <span ng-switch-when="USERNAME_INVALID" my-i18n="error_modal_username_invalid_description"></span>
<span ng-switch-when="USERNAME_OCCUPIED" my-i18n="error_modal_username_occupied_description"></span> <span ng-switch-when="USERNAME_OCCUPIED" my-i18n="error_modal_username_occupied_description"></span>
<span ng-switch-when="MULTIPLE_TABS_OPEN" my-i18n="error_modal_multiple_open_tabs"></span>
<div ng-switch-default ng-switch="error.code"> <div ng-switch-default ng-switch="error.code">
<span ng-switch-when="400" my-i18n="error_modal_bad_request_description"></span> <span ng-switch-when="400" my-i18n="error_modal_bad_request_description"></span>

Loading…
Cancel
Save