diff --git a/app/img/Manytabs.png b/app/img/Manytabs.png
new file mode 100644
index 00000000..4aed5310
Binary files /dev/null and b/app/img/Manytabs.png differ
diff --git a/app/js/lib/mtproto_wrapper.js b/app/js/lib/mtproto_wrapper.js
index 7b7385f7..a02fa672 100644
--- a/app/js/lib/mtproto_wrapper.js
+++ b/app/js/lib/mtproto_wrapper.js
@@ -698,13 +698,13 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
};
})
-.service('MtpSingleInstanceService', function (_, $rootScope, $interval, Storage, AppRuntimeManager, IdleManager, ErrorService, MtpNetworkerFactory) {
+.service('MtpSingleInstanceService', function (_, $rootScope, $compile, $timeout, $interval, $modalStack, Storage, AppRuntimeManager, IdleManager, ErrorService, MtpNetworkerFactory) {
var instanceID = nextRandomInt(0xFFFFFFFF);
var started = false;
var masterInstance = false;
- var startTime = tsNow();
- var errorShowTime = 0;
+ var deactivatePromise = false;
+ var deactivated = false;
function start() {
if (!started && !Config.Navigator.mobile && !Config.Modes.packed) {
@@ -712,7 +712,6 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
IdleManager.start();
- startTime = tsNow();
$rootScope.$watch('idle.isIDLE', checkInstance);
$interval(checkInstance, 5000);
checkInstance();
@@ -727,7 +726,38 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
Storage.remove(masterInstance ? 'xt_instance' : 'xt_idle_instance');
}
+ function deactivateInstance () {
+ if (masterInstance || deactivated) {
+ return false;
+ }
+ console.log(dT(), 'deactivate');
+ deactivatePromise = false;
+ deactivated = true;
+ clearInstance();
+ $modalStack.dismissAll();
+
+ document.title = _('inactive_tab_title_raw');
+
+ var inactivePageCompiled = $compile('');
+
+ var scope = $rootScope.$new(true);
+ scope.close = function () {
+ AppRuntimeManager.close();
+ };
+ scope.reload = function () {
+ AppRuntimeManager.reload();
+ };
+ inactivePageCompiled(scope, function (clonedElement) {
+ $('.page_wrap').hide();
+ $(clonedElement).appendTo($('body'));
+ });
+ $rootScope.idle.deactivated = true;
+ }
+
function checkInstance() {
+ if (deactivated) {
+ return false;
+ }
var time = tsNow();
var idle = $rootScope.idle && $rootScope.idle.isIDLE;
var newInstance = {id: instanceID, idle: idle, time: time};
@@ -736,38 +766,36 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
var curInstance = result[0],
idleInstance = result[1];
- if (!curInstance ||
- curInstance.time < time - 60000 ||
+ // console.log(dT(), 'check instance', newInstance, curInstance, idleInstance);
+ if (!idle ||
+ !curInstance ||
curInstance.id == instanceID ||
- curInstance.idle ||
- !idle) {
+ curInstance.time < time - 60000) {
- if (idleInstance) {
- if (idleInstance.id == instanceID) {
- Storage.remove('xt_idle_instance');
- }
- else if (idleInstance.time > time - 10000 &&
- time > errorShowTime) {
-
- ErrorService.alert(
- _('error_modal_warning_title_raw'),
- _('error_modal_multiple_open_tabs_raw')
- );
- errorShowTime += tsNow() + 60000;
- }
+ if (idleInstance &&
+ idleInstance.id == instanceID) {
+ Storage.remove('xt_idle_instance');
}
Storage.set({xt_instance: newInstance});
if (!masterInstance) {
MtpNetworkerFactory.startAll();
+ console.warn(dT(), 'now master instance', newInstance);
}
masterInstance = true;
+ if (deactivatePromise) {
+ $timeout.cancel(deactivatePromise);
+ deactivatePromise = false;
+ }
} else {
Storage.set({xt_idle_instance: newInstance});
if (masterInstance) {
MtpNetworkerFactory.stopAll();
+ console.warn(dT(), 'now idle instance', newInstance);
+ if (!deactivatePromise) {
+ deactivatePromise = $timeout(deactivateInstance, 30000);
+ }
}
masterInstance = false;
-
}
});
}
diff --git a/app/js/locales/en-us.json b/app/js/locales/en-us.json
index ceefa955..b0a7dec7 100644
--- a/app/js/locales/en-us.json
+++ b/app/js/locales/en-us.json
@@ -360,7 +360,6 @@
"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_tech_details": "Technical details here",
- "error_modal_multiple_open_tabs": "Please close other Telegram app tabs.",
"error_modal_recovery_na_description": "Since you haven't provided a recovery e-mail when setting up your password, your remaining options are either to remember your password or to reset your account.",
"error_modal_password_success_descripion": "Your password for Two-Step Verification is now active.",
"error_modal_password_disabled_descripion": "You have disabled Two-Step Verification.",
@@ -531,6 +530,12 @@
"phonebook_modal_submit_active": "Importing",
"phonebook_modal_submit": "Import contacts",
+ "inactive_tab_title": "Telegram: Zzz...",
+ "inactive_title": "Such error, many tabs",
+ "inactive_description_md": "Telegram supports only one active tab with the app.\nPlease reload this page to continue using this tab or close it",
+ "inactive_reload_btn": "Reload App",
+
+
"country_select_modal_country_ab": "Abkhazia",
"country_select_modal_country_af": "Afghanistan",
"country_select_modal_country_ax": "Ă…land Islands",
diff --git a/app/js/services.js b/app/js/services.js
index a8a82c8f..6857ab50 100755
--- a/app/js/services.js
+++ b/app/js/services.js
@@ -2908,13 +2908,22 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var titleBackup = document.title,
titleChanged = false,
- titleCnt = 0,
titlePromise;
var prevFavicon;
+ var stopped = false;
var settings = {};
+ $rootScope.$watch('idle.deactivated', function (newVal) {
+ if (newVal) {
+ stop();
+ }
+ });
+
$rootScope.$watch('idle.isIDLE', function (newVal) {
+ if (stopped) {
+ return;
+ }
if (!newVal) {
notificationsClear();
}
@@ -2928,12 +2937,10 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
titleBackup = document.title;
titlePromise = $interval(function () {
- if (!notificationsCount || ((titleCnt++) % 2)) {
- if (titleChanged) {
- titleChanged = false;
- document.title = titleBackup;
- setFavicon();
- }
+ if (titleChanged || !notificationsCount) {
+ titleChanged = false;
+ document.title = titleBackup;
+ setFavicon();
} else {
titleChanged = true;
document.title = langNotificationsPluralize(notificationsCount);
@@ -3028,7 +3035,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
faviconEl.parentNode.replaceChild(link, faviconEl);
faviconEl = link;
- prevFavicon = href
+ prevFavicon = href;
}
function savePeerSettings (peerID, settings) {
@@ -3080,12 +3087,22 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} catch (e) {}
}
+ function stop () {
+ notificationsClear();
+ $interval.cancel(titlePromise);
+ setFavicon();
+ stopped = true;
+ }
+
function requestPermission() {
Notification.requestPermission();
$($window).off('click', requestPermission);
}
function notify (data) {
+ if (stopped) {
+ return;
+ }
// console.log('notify', $rootScope.idle.isIDLE, notificationsUiSupport);
// FFOS Notification blob src bug workaround
diff --git a/app/less/app.less b/app/less/app.less
index fec99eb6..5f516392 100644
--- a/app/less/app.less
+++ b/app/less/app.less
@@ -4118,6 +4118,30 @@ a.countries_modal_search_clear {
}
}
+.inactive_page_content {
+ max-width: 400px;
+ margin: 0 auto;
+ text-align: center;
+}
+.inactive_image {
+ display: block;
+ background: url(../img/Manytabs.png) no-repeat 0 0;
+ width: 341px;
+ height: 262px;
+ margin: 0 auto;
+}
+.inactive_title {
+ font-size: 18px;
+ color: #444444;
+}
+.inactive_description {
+ color: #666666;
+ font-size: 15px;
+ line-height: 150%;
+}
+.inactive_actions {
+ margin-top: 15px;
+}
@media print {
diff --git a/app/partials/desktop/inactive.html b/app/partials/desktop/inactive.html
new file mode 100644
index 00000000..ba52114a
--- /dev/null
+++ b/app/partials/desktop/inactive.html
@@ -0,0 +1,13 @@
+
\ No newline at end of file