diff --git a/app/css/app.css b/app/css/app.css index 9def9d17..4796c549 100644 --- a/app/css/app.css +++ b/app/css/app.css @@ -2052,6 +2052,32 @@ img.img_fullsize { font-size: 14px; line-height: 160%; } +.error_modal_details textarea { + display: block; + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + padding: 0; + font-size: 10px; + line-height: 100%; + white-space: pre-wrap; + padding: 4px; + margin: 10px 0 10px; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 4px; + width: 100%; + text-align: left; +} +.error_modal_details div { + padding: 0 20px; + font-size: 13px; + text-align: center; +} +.error_modal_details div a { + color: #999; +} diff --git a/app/js/controllers.js b/app/js/controllers.js index 207ac177..6da69c28 100644 --- a/app/js/controllers.js +++ b/app/js/controllers.js @@ -98,6 +98,7 @@ angular.module('myApp.controllers', []) switch (error.type) { case 'PHONE_NUMBER_INVALID': $scope.error = {field: 'phone'}; + error.handled = true; break; } }); @@ -106,10 +107,8 @@ angular.module('myApp.controllers', []) switch (error.type) { case 'PHONE_NUMBER_INVALID': $scope.error = {field: 'phone'}; + error.handled = true; break; - - default: - ErrorService.alert('Unknown error occured', 'Please check your internet connection or install the latest version of Google Chrome browser.'); } }); } @@ -132,8 +131,10 @@ angular.module('myApp.controllers', []) MtpApiManager.invokeApi(method, params, options).then(saveAuth, function (error) { $scope.progress.enabled = false; if (error.code == 400 && error.type == 'PHONE_NUMBER_UNOCCUPIED') { + error.handled = true; return $scope.logIn(true); } else if (error.code == 400 && error.type == 'PHONE_NUMBER_OCCUPIED') { + error.handled = true; return $scope.logIn(false); } @@ -141,12 +142,15 @@ angular.module('myApp.controllers', []) switch (error.type) { case 'FIRSTNAME_INVALID': $scope.error = {field: 'first_name'}; + error.handled = true; break; case 'LASTNAME_INVALID': $scope.error = {field: 'last_name'}; + error.handled = true; break; case 'PHONE_CODE_INVALID': $scope.error = {field: 'phone_code'}; + error.handled = true; break; } }); @@ -313,6 +317,7 @@ angular.module('myApp.controllers', []) MtpApiManager.logOut()['finally'](function () { $location.url('/login'); }); + error.handled = true; } }); } @@ -1083,12 +1088,6 @@ angular.module('myApp.controllers', []) } }).then(function (updateResult) { onStatedMessage(updateResult); - }, function (error) { - switch (error.code) { - case 400: - ErrorService.alert('Bad photo', 'The photo is invalid, please select another file.'); - break; - } }); })['finally'](function () { $scope.photo.updating = false; @@ -1121,7 +1120,7 @@ angular.module('myApp.controllers', []) }) - .controller('SettingsModalController', function ($rootScope, $scope, $timeout, AppUsersManager, AppChatsManager, MtpApiManager, AppConfigManager, NotificationsManager, MtpApiFileManager, ApiUpdatesManager, ErrorService) { + .controller('SettingsModalController', function ($rootScope, $scope, $timeout, AppUsersManager, AppChatsManager, MtpApiManager, AppConfigManager, NotificationsManager, MtpApiFileManager, ApiUpdatesManager) { $scope.profile = {}; @@ -1247,13 +1246,16 @@ angular.module('myApp.controllers', []) switch (error.type) { case 'FIRSTNAME_INVALID': $scope.error = {field: 'first_name'}; + error.handled = true; break; case 'LASTNAME_INVALID': $scope.error = {field: 'last_name'}; + error.handled = true; break; case 'NAME_NOT_MODIFIED': + error.handled = true; $scope.error = {}; break; } diff --git a/app/js/lib/mtproto.js b/app/js/lib/mtproto.js index 00cc115d..353fd3da 100644 --- a/app/js/lib/mtproto.js +++ b/app/js/lib/mtproto.js @@ -2457,7 +2457,7 @@ factory('MtpNetworkerFactory', function (MtpDcConfigurator, MtpMessageIdGenerato }). -factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworkerFactory, $q) { +factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworkerFactory, ErrorService, $q) { var cachedNetworkers = {}, cachedUploadNetworkers = {}, cachedExportPromise = {}, @@ -2489,6 +2489,7 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker AppConfigManager.remove('dc' + baseDcID + '_auth_key'); } baseDcID = false; + error.handled = true; }); } @@ -2547,6 +2548,25 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker options = options || {}; var deferred = $q.defer(), + rejectPromise = function (error) { + if (!error) { + error = {type: 'ERROR_EMPTY'}; + } else if (!angular.isObject(error)) { + error = {message: error}; + } + deferred.reject(error); + + if (!options.noErrorBox) { + error.input = method; + error.stack = error.stack || stack; + setTimeout(function () { + if (!error.handled) { + ErrorService.show({error: error}); + error.handled = true; + } + }, 100); + } + }, dcID, networkerPromise; @@ -2558,7 +2578,8 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker }); } - var cachedNetworker; + var cachedNetworker, + stack = false; networkerPromise.then(function (networker) { return (cachedNetworker = networker).wrapApiCall(method, params, options).then( @@ -2574,11 +2595,11 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker if (cachedExportPromise[dcID] === undefined) { var exportDeferred = $q.defer(); - mtpInvokeApi('auth.exportAuthorization', {dc_id: dcID}).then(function (exportedAuth) { + mtpInvokeApi('auth.exportAuthorization', {dc_id: dcID}, {noErrorBox: true}).then(function (exportedAuth) { mtpInvokeApi('auth.importAuthorization', { id: exportedAuth.id, bytes: exportedAuth.bytes - }, {dcID: dcID}).then(function () { + }, {dcID: dcID, noErrorBox: true}).then(function () { exportDeferred.resolve(); }, function (e) { exportDeferred.reject(e); @@ -2594,10 +2615,10 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker (cachedNetworker = networker).wrapApiCall(method, params, options).then(function (result) { deferred.resolve(result); }, function (error) { - deferred.reject(error); + rejectPromise(error); }); }, function (error) { - deferred.reject(error); + rejectPromise(error); }); } else if (error.code == 303) { @@ -2613,19 +2634,25 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker networker.wrapApiCall(method, params, options).then(function (result) { deferred.resolve(result); }, function (error) { - deferred.reject(error); + rejectPromise(error); }); }); } } else { - deferred.reject(error); + rejectPromise(error); } }); }, function (error) { - deferred.reject(error); + rejectPromise(error); }); + if (!(stack = (stack || (new Error()).stack))) { + try {1 = 0;} catch (e) { + stack = e.stack || ''; + } + } + return deferred.promise; }; diff --git a/app/js/services.js b/app/js/services.js index c461fc1b..b81ebeff 100644 --- a/app/js/services.js +++ b/app/js/services.js @@ -318,7 +318,7 @@ angular.module('myApp.services', []) }); return MtpApiManager.invokeApi('contacts.deleteContacts', { id: ids - }, function () { + }).then(function () { angular.forEach(userIDs, function (userID) { onContactUpdated(userID, false); }); @@ -779,7 +779,7 @@ angular.module('myApp.services', []) } function fillHistoryStorage (inputPeer, maxID, fullLimit, historyStorage) { - // console.log('fill history storage', inputPeer, maxID, fullLimit, angular.copy(historyStorage)); + console.log('fill history storage', inputPeer, maxID, fullLimit, angular.copy(historyStorage)); return MtpApiManager.invokeApi('messages.getHistory', { peer: inputPeer, offset: 0, @@ -926,8 +926,6 @@ angular.module('myApp.services', []) return deletedMessageIDs; }); - - } function processAffectedHistory (inputPeer, affectedHistory, method) { @@ -2798,7 +2796,7 @@ angular.module('myApp.services', []) lastOnlineUpdated = offline ? 0 : date; return MtpApiManager.invokeApi('account.updateStatus', { offline: offline - }); + }, {noErrorBox: true}); } function checkIDLE() { @@ -3006,16 +3004,30 @@ angular.module('myApp.services', []) .service('ErrorService', function ($rootScope, $modal) { + var shownBoxes = 0; + function show (params, options) { + if (shownBoxes >= 2) { + console.log('Skip error box, too many open', shownBoxes, params, options); + return false; + } + options = options || {}; var scope = $rootScope.$new(); angular.extend(scope, params); - return $modal.open({ + shownBoxes++; + var modal = $modal.open({ templateUrl: 'partials/error_modal.html', scope: scope, windowClass: options.windowClass || 'error_modal_window' }); + + modal.result['finally'](function () { + shownBoxes--; + }); + + return modal; } function alert (title, description) { diff --git a/app/partials/error_modal.html b/app/partials/error_modal.html index f492053c..314502f3 100644 --- a/app/partials/error_modal.html +++ b/app/partials/error_modal.html @@ -34,6 +34,9 @@ The photo dimensions are invalid, please select another file. + + The photo you provided is too small. + Sorry, there is no Telegram account for {{phone | phoneNumber}}

Please sign up using our mobile apps for iOS or Android. @@ -47,12 +50,16 @@ The page was not found. You are performing too many actions. Please try again later. Internal server error occured. Please try again later. + -
-
{{error.originalError}}
- Click here for technical details. -
+ +
+ +
+ Technical details here