Browse Source

Fixed #214 - Now showing all API errors in modal boxes.

master
Igor Zhukov 11 years ago
parent
commit
8e97680c4f
  1. 26
      app/css/app.css
  2. 22
      app/js/controllers.js
  3. 45
      app/js/lib/mtproto.js
  4. 24
      app/js/services.js
  5. 15
      app/partials/error_modal.html

26
app/css/app.css

@ -2052,6 +2052,32 @@ img.img_fullsize {
font-size: 14px; font-size: 14px;
line-height: 160%; 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;
}

22
app/js/controllers.js

@ -98,6 +98,7 @@ angular.module('myApp.controllers', [])
switch (error.type) { switch (error.type) {
case 'PHONE_NUMBER_INVALID': case 'PHONE_NUMBER_INVALID':
$scope.error = {field: 'phone'}; $scope.error = {field: 'phone'};
error.handled = true;
break; break;
} }
}); });
@ -106,10 +107,8 @@ angular.module('myApp.controllers', [])
switch (error.type) { switch (error.type) {
case 'PHONE_NUMBER_INVALID': case 'PHONE_NUMBER_INVALID':
$scope.error = {field: 'phone'}; $scope.error = {field: 'phone'};
error.handled = true;
break; 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) { MtpApiManager.invokeApi(method, params, options).then(saveAuth, function (error) {
$scope.progress.enabled = false; $scope.progress.enabled = false;
if (error.code == 400 && error.type == 'PHONE_NUMBER_UNOCCUPIED') { if (error.code == 400 && error.type == 'PHONE_NUMBER_UNOCCUPIED') {
error.handled = true;
return $scope.logIn(true); return $scope.logIn(true);
} else if (error.code == 400 && error.type == 'PHONE_NUMBER_OCCUPIED') { } else if (error.code == 400 && error.type == 'PHONE_NUMBER_OCCUPIED') {
error.handled = true;
return $scope.logIn(false); return $scope.logIn(false);
} }
@ -141,12 +142,15 @@ angular.module('myApp.controllers', [])
switch (error.type) { switch (error.type) {
case 'FIRSTNAME_INVALID': case 'FIRSTNAME_INVALID':
$scope.error = {field: 'first_name'}; $scope.error = {field: 'first_name'};
error.handled = true;
break; break;
case 'LASTNAME_INVALID': case 'LASTNAME_INVALID':
$scope.error = {field: 'last_name'}; $scope.error = {field: 'last_name'};
error.handled = true;
break; break;
case 'PHONE_CODE_INVALID': case 'PHONE_CODE_INVALID':
$scope.error = {field: 'phone_code'}; $scope.error = {field: 'phone_code'};
error.handled = true;
break; break;
} }
}); });
@ -313,6 +317,7 @@ angular.module('myApp.controllers', [])
MtpApiManager.logOut()['finally'](function () { MtpApiManager.logOut()['finally'](function () {
$location.url('/login'); $location.url('/login');
}); });
error.handled = true;
} }
}); });
} }
@ -1083,12 +1088,6 @@ angular.module('myApp.controllers', [])
} }
}).then(function (updateResult) { }).then(function (updateResult) {
onStatedMessage(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 () { })['finally'](function () {
$scope.photo.updating = false; $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 = {}; $scope.profile = {};
@ -1247,13 +1246,16 @@ angular.module('myApp.controllers', [])
switch (error.type) { switch (error.type) {
case 'FIRSTNAME_INVALID': case 'FIRSTNAME_INVALID':
$scope.error = {field: 'first_name'}; $scope.error = {field: 'first_name'};
error.handled = true;
break; break;
case 'LASTNAME_INVALID': case 'LASTNAME_INVALID':
$scope.error = {field: 'last_name'}; $scope.error = {field: 'last_name'};
error.handled = true;
break; break;
case 'NAME_NOT_MODIFIED': case 'NAME_NOT_MODIFIED':
error.handled = true;
$scope.error = {}; $scope.error = {};
break; break;
} }

45
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 = {}, var cachedNetworkers = {},
cachedUploadNetworkers = {}, cachedUploadNetworkers = {},
cachedExportPromise = {}, cachedExportPromise = {},
@ -2489,6 +2489,7 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker
AppConfigManager.remove('dc' + baseDcID + '_auth_key'); AppConfigManager.remove('dc' + baseDcID + '_auth_key');
} }
baseDcID = false; baseDcID = false;
error.handled = true;
}); });
} }
@ -2547,6 +2548,25 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker
options = options || {}; options = options || {};
var deferred = $q.defer(), 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, dcID,
networkerPromise; networkerPromise;
@ -2558,7 +2578,8 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker
}); });
} }
var cachedNetworker; var cachedNetworker,
stack = false;
networkerPromise.then(function (networker) { networkerPromise.then(function (networker) {
return (cachedNetworker = networker).wrapApiCall(method, params, options).then( return (cachedNetworker = networker).wrapApiCall(method, params, options).then(
@ -2574,11 +2595,11 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker
if (cachedExportPromise[dcID] === undefined) { if (cachedExportPromise[dcID] === undefined) {
var exportDeferred = $q.defer(); 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', { mtpInvokeApi('auth.importAuthorization', {
id: exportedAuth.id, id: exportedAuth.id,
bytes: exportedAuth.bytes bytes: exportedAuth.bytes
}, {dcID: dcID}).then(function () { }, {dcID: dcID, noErrorBox: true}).then(function () {
exportDeferred.resolve(); exportDeferred.resolve();
}, function (e) { }, function (e) {
exportDeferred.reject(e); exportDeferred.reject(e);
@ -2594,10 +2615,10 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker
(cachedNetworker = networker).wrapApiCall(method, params, options).then(function (result) { (cachedNetworker = networker).wrapApiCall(method, params, options).then(function (result) {
deferred.resolve(result); deferred.resolve(result);
}, function (error) { }, function (error) {
deferred.reject(error); rejectPromise(error);
}); });
}, function (error) { }, function (error) {
deferred.reject(error); rejectPromise(error);
}); });
} }
else if (error.code == 303) { else if (error.code == 303) {
@ -2613,19 +2634,25 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker
networker.wrapApiCall(method, params, options).then(function (result) { networker.wrapApiCall(method, params, options).then(function (result) {
deferred.resolve(result); deferred.resolve(result);
}, function (error) { }, function (error) {
deferred.reject(error); rejectPromise(error);
}); });
}); });
} }
} }
else { else {
deferred.reject(error); rejectPromise(error);
} }
}); });
}, function (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; return deferred.promise;
}; };

24
app/js/services.js

@ -318,7 +318,7 @@ angular.module('myApp.services', [])
}); });
return MtpApiManager.invokeApi('contacts.deleteContacts', { return MtpApiManager.invokeApi('contacts.deleteContacts', {
id: ids id: ids
}, function () { }).then(function () {
angular.forEach(userIDs, function (userID) { angular.forEach(userIDs, function (userID) {
onContactUpdated(userID, false); onContactUpdated(userID, false);
}); });
@ -779,7 +779,7 @@ angular.module('myApp.services', [])
} }
function fillHistoryStorage (inputPeer, maxID, fullLimit, historyStorage) { 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', { return MtpApiManager.invokeApi('messages.getHistory', {
peer: inputPeer, peer: inputPeer,
offset: 0, offset: 0,
@ -926,8 +926,6 @@ angular.module('myApp.services', [])
return deletedMessageIDs; return deletedMessageIDs;
}); });
} }
function processAffectedHistory (inputPeer, affectedHistory, method) { function processAffectedHistory (inputPeer, affectedHistory, method) {
@ -2798,7 +2796,7 @@ angular.module('myApp.services', [])
lastOnlineUpdated = offline ? 0 : date; lastOnlineUpdated = offline ? 0 : date;
return MtpApiManager.invokeApi('account.updateStatus', { return MtpApiManager.invokeApi('account.updateStatus', {
offline: offline offline: offline
}); }, {noErrorBox: true});
} }
function checkIDLE() { function checkIDLE() {
@ -3006,16 +3004,30 @@ angular.module('myApp.services', [])
.service('ErrorService', function ($rootScope, $modal) { .service('ErrorService', function ($rootScope, $modal) {
var shownBoxes = 0;
function show (params, options) { function show (params, options) {
if (shownBoxes >= 2) {
console.log('Skip error box, too many open', shownBoxes, params, options);
return false;
}
options = options || {}; options = options || {};
var scope = $rootScope.$new(); var scope = $rootScope.$new();
angular.extend(scope, params); angular.extend(scope, params);
return $modal.open({ shownBoxes++;
var modal = $modal.open({
templateUrl: 'partials/error_modal.html', templateUrl: 'partials/error_modal.html',
scope: scope, scope: scope,
windowClass: options.windowClass || 'error_modal_window' windowClass: options.windowClass || 'error_modal_window'
}); });
modal.result['finally'](function () {
shownBoxes--;
});
return modal;
} }
function alert (title, description) { function alert (title, description) {

15
app/partials/error_modal.html

@ -34,6 +34,9 @@
<span ng-switch-when="PHOTO_INVALID_DIMENSIONS"> <span ng-switch-when="PHOTO_INVALID_DIMENSIONS">
The photo dimensions are invalid, please select another file. The photo dimensions are invalid, please select another file.
</span> </span>
<span ng-switch-when="PHOTO_CROP_SIZE_SMALL">
The photo you provided is too small.
</span>
<span ng-switch-when="ACCOUNT_REQUIRED"> <span ng-switch-when="ACCOUNT_REQUIRED">
Sorry, there is no <strong>Telegram</strong> account for {{phone | phoneNumber}}<br/><br/> Sorry, there is no <strong>Telegram</strong> account for {{phone | phoneNumber}}<br/><br/>
Please <strong>sign up</strong> using our mobile apps for <a href="https://telegram.org/" target="_blank">iOS</a> or <a href="https://telegram.org/" target="_blank">Android</a>. Please <strong>sign up</strong> using our mobile apps for <a href="https://telegram.org/" target="_blank">iOS</a> or <a href="https://telegram.org/" target="_blank">Android</a>.
@ -47,12 +50,16 @@
<span ng-switch-when="404">The page was not found.</span> <span ng-switch-when="404">The page was not found.</span>
<span ng-switch-when="420">You are performing too many actions. Please try again later.</span> <span ng-switch-when="420">You are performing too many actions. Please try again later.</span>
<span ng-switch-default>Internal server error occured. Please try again later.</span> <span ng-switch-default>Internal server error occured. Please try again later.</span>
</div>
<div ng-if="error.originalError" ng-switch="showErrorDetails"> </div>
<pre ng-switch-when="true"><code>{{error.originalError}}</code></pre>
<a ng-switch-default href="" ng-click="showErrorDetails = true">Click here</a> for technical details.
</div>
<div ng-if="error" class="error_modal_details" ng-switch="error.detailsShown">
<textarea ng-switch-when="true" rows="3" onclick="this.select()">Method: {{error.input || 'N/A'}}
Result: {{error.originalError || error}}
Stack: {{error.stack}}</textarea>
<div ng-switch-default>
<a href="" ng-click="error.detailsShown = true">Technical details here</a>
</div> </div>
</div> </div>

Loading…
Cancel
Save