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