Browse Source

IE10+ fixes

Textfield height
Unsupported media modal
Download blobs
master
Igor Zhukov 10 years ago
parent
commit
847b7df54e
  1. 6
      app/css/app.css
  2. 2
      app/js/controllers.js
  3. 103
      app/js/directives.js
  4. 16
      app/js/lib/mtproto_wrapper.js
  5. 22
      app/js/lib/ng_utils.js
  6. 2
      app/js/locales/en-us.json
  7. 41
      app/js/services.js
  8. 2
      app/partials/desktop/error_modal.html

6
app/css/app.css

@ -1963,12 +1963,14 @@ img.img_fullsize { @@ -1963,12 +1963,14 @@ img.img_fullsize {
}
.emoji-wysiwyg-editor {
box-sizing: content-box;
font-size: 12px;
margin-bottom: 10px;
padding: 6px;
min-height: 50px;
min-height: 34px;
height: auto;
max-height: 300px;
width: auto;
max-height: 284px;
overflow: auto;
line-height: 17px;

2
app/js/controllers.js

@ -1791,7 +1791,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1791,7 +1791,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
};
$scope.download = function () {
$rootScope.downloadVideo($scope.videoID)
AppVideoManager.saveVideoFile($scope.videoID);
};
$scope.$on('history_delete', function (e, historyUpdate) {

103
app/js/directives.js

@ -1270,7 +1270,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1270,7 +1270,7 @@ angular.module('myApp.directives', ['myApp.filters'])
}
})
.directive('myLoadThumb', function(MtpApiFileManager) {
.directive('myLoadThumb', function(MtpApiFileManager, FileManager) {
return {
link: link,
@ -1282,15 +1282,15 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1282,15 +1282,15 @@ angular.module('myApp.directives', ['myApp.filters'])
function link ($scope, element, attrs) {
var counter = 0;
var cachedSrc = MtpApiFileManager.getCachedFile(
var cachedBlob = MtpApiFileManager.getCachedFile(
$scope.thumb &&
$scope.thumb.location &&
!$scope.thumb.location.empty &&
$scope.thumb.location
);
if (cachedSrc) {
element.attr('src', cachedSrc);
if (cachedBlob) {
element.attr('src', FileManager.getUrl(cachedBlob, 'image/jpeg'));
}
if ($scope.thumb && $scope.thumb.width && $scope.thumb.height) {
element.attr('width', $scope.thumb.width);
@ -1311,9 +1311,9 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1311,9 +1311,9 @@ angular.module('myApp.directives', ['myApp.filters'])
return;
}
var cachedSrc = MtpApiFileManager.getCachedFile(newLocation);
if (cachedSrc) {
element.attr('src', cachedSrc);
var cachedBlob = MtpApiFileManager.getCachedFile(newLocation);
if (cachedBlob) {
element.attr('src', FileManager.getUrl(cachedBlob, 'image/jpeg'));
cleanup();
return;
}
@ -1322,9 +1322,9 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1322,9 +1322,9 @@ angular.module('myApp.directives', ['myApp.filters'])
element.attr('src', $scope.thumb.placeholder || 'img/blank.gif');
}
MtpApiFileManager.downloadSmallFile($scope.thumb.location).then(function (url) {
MtpApiFileManager.downloadSmallFile($scope.thumb.location).then(function (blob) {
if (counterSaved == counter) {
element.attr('src', url);
element.attr('src', FileManager.getUrl(blob, 'image/jpeg'));
cleanup();
}
}, function (e) {
@ -1348,7 +1348,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1348,7 +1348,7 @@ angular.module('myApp.directives', ['myApp.filters'])
})
.directive('myLoadFullPhoto', function(MtpApiFileManager, _) {
.directive('myLoadFullPhoto', function(MtpApiFileManager, FileManager, _) {
return {
link: link,
@ -1402,10 +1402,10 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1402,10 +1402,10 @@ angular.module('myApp.directives', ['myApp.filters'])
$scope.progress = {enabled: true, percent: 0};
apiPromise.then(function (url) {
apiPromise.then(function (blob) {
if (curJump == jump) {
$scope.progress.enabled = false;
imgElement.src = url;
imgElement.src = FileManager.getUrl(blob, 'image/jpeg');
resize();
}
}, function (e) {
@ -1431,7 +1431,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1431,7 +1431,7 @@ angular.module('myApp.directives', ['myApp.filters'])
})
.directive('myLoadVideo', function($sce, AppVideoManager, _) {
.directive('myLoadVideo', function($sce, AppVideoManager, ErrorService, _) {
return {
link: link,
@ -1448,6 +1448,35 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1448,6 +1448,35 @@ angular.module('myApp.directives', ['myApp.filters'])
downloadPromise.then(function () {
$scope.$emit('ui_height');
onContentLoaded(function () {
var videoEl = $('video', element)[0];
if (videoEl) {
var errorAlready = false;
var onVideoError = function (event) {
if (errorAlready) {
return;
}
if (!event.target ||
!event.target.error ||
event.target.error.code == event.target.error.MEDIA_ERR_DECODE ||
event.target.error.code == event.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED) {
errorAlready = true;
ErrorService.show({
error: {
type: 'MEDIA_TYPE_NOT_SUPPORTED',
originalError: event.target && event.target.error
}
});
}
};
videoEl.addEventListener('error', onVideoError, true);
$(videoEl).on('$destroy', function () {
errorAlready = true;
videoEl.removeEventListener('error', onVideoError);
});
}
});
}, function (e) {
console.log('Download video failed', e, $scope.video);
@ -1516,7 +1545,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1516,7 +1545,7 @@ angular.module('myApp.directives', ['myApp.filters'])
}
})
.directive('myLoadDocument', function(MtpApiFileManager, AppDocsManager) {
.directive('myLoadDocument', function(MtpApiFileManager, AppDocsManager, FileManager) {
return {
link: link,
@ -1567,7 +1596,8 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1567,7 +1596,8 @@ angular.module('myApp.directives', ['myApp.filters'])
var checkSizesInt;
var realImageWidth, realImageHeight;
AppDocsManager.downloadDoc($scope.document.id).then(function (url) {
AppDocsManager.downloadDoc($scope.document.id).then(function (blob) {
var url = FileManager.getUrl(blob, $scope.document.mime_type);
var image = new Image();
var limit = 100; // 2 sec
var checkSizes = function (e) {
@ -2012,7 +2042,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -2012,7 +2042,7 @@ angular.module('myApp.directives', ['myApp.filters'])
}
})
.directive('myAudioPlayer', function ($timeout, $q, Storage, AppAudioManager, AppDocsManager) {
.directive('myAudioPlayer', function ($timeout, $q, Storage, AppAudioManager, AppDocsManager, ErrorService) {
var currentPlayer = false;
var audioVolume = 0.5;
@ -2023,6 +2053,20 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -2023,6 +2053,20 @@ angular.module('myApp.directives', ['myApp.filters'])
}
});
var onAudioError = function (event) {
if (!event.target ||
!event.target.error ||
event.target.error.code == event.target.error.MEDIA_ERR_DECODE ||
event.target.error.code == event.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED) {
ErrorService.show({
error: {
type: 'MEDIA_TYPE_NOT_SUPPORTED',
originalError: event.target && event.target.error
}
});
}
};
return {
link: link,
scope: {
@ -2077,6 +2121,33 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -2077,6 +2121,33 @@ angular.module('myApp.directives', ['myApp.filters'])
downloadPromise.then(function () {
onContentLoaded(function () {
var audioEl = $('audio', element)[0];
if (audioEl) {
var errorAlready = false;
var onAudioError = function (event) {
if (errorAlready) {
return;
}
if (!event.target ||
!event.target.error ||
event.target.error.code == event.target.error.MEDIA_ERR_DECODE ||
event.target.error.code == event.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED) {
errorAlready = true;
ErrorService.show({
error: {
type: 'MEDIA_TYPE_NOT_SUPPORTED',
originalError: event.target && event.target.error
}
});
}
};
audioEl.addEventListener('error', onAudioError, true);
$(audioEl).on('$destroy', function () {
errorAlready = true;
audioEl.removeEventListener('error', onAudioError);
});
}
checkPlayer($scope.mediaPlayer.player);
$scope.mediaPlayer.player.setVolume(audioVolume);
$scope.mediaPlayer.player.play();

16
app/js/lib/mtproto_wrapper.js

@ -328,7 +328,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto']) @@ -328,7 +328,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
if (!cachedSavePromises[fileName]) {
cachedSavePromises[fileName] = getFileStorage().saveFile(fileName, bytes).then(function (blob) {
return cachedDownloads[fileName] = FileManager.getUrl(blob, mimeType);
return cachedDownloads[fileName] = blob;
});
}
return cachedSavePromises[fileName];
@ -350,7 +350,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto']) @@ -350,7 +350,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
var fileStorage = getFileStorage();
return cachedDownloadPromises[fileName] = fileStorage.getFile(fileName).then(function (blob) {
return cachedDownloads[fileName] = FileManager.getUrl(blob, mimeType);
return cachedDownloads[fileName] = blob;
}, function () {
var downloadPromise = downloadRequest(location.dc_id, function () {
// console.log('next small promise');
@ -368,7 +368,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto']) @@ -368,7 +368,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
return fileStorage.getFileWriter(fileName, mimeType).then(function (fileWriter) {
return downloadPromise.then(function (result) {
return FileManager.write(fileWriter, result.bytes).then(function () {
return cachedDownloads[fileName] = FileManager.getUrl(fileWriter.finalize(), mimeType);
return cachedDownloads[fileName] = fileWriter.finalize();
});
});
});
@ -400,10 +400,8 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto']) @@ -400,10 +400,8 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
if (cachedPromise) {
if (toFileEntry) {
return cachedPromise.then(function (url) {
return fileStorage.getFile(fileName).then(function (blob) {
return FileManager.copy(blob, toFileEntry);
});
return cachedPromise.then(function (blob) {
return FileManager.copy(blob, toFileEntry);
})
}
return cachedPromise;
@ -430,7 +428,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto']) @@ -430,7 +428,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
deferred.resolve();
}, errorHandler);
} else {
deferred.resolve(cachedDownloads[fileName] = FileManager.getUrl(blob, mimeType));
deferred.resolve(cachedDownloads[fileName] = blob);
}
}, function () {
var fileWriterPromise = toFileEntry ? FileManager.getFileWriter(toFileEntry) : fileStorage.getFileWriter(fileName, mimeType);
@ -476,7 +474,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto']) @@ -476,7 +474,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
if (toFileEntry) {
deferred.resolve();
} else {
deferred.resolve(cachedDownloads[fileName] = FileManager.getUrl(fileWriter.finalize(), mimeType));
deferred.resolve(cachedDownloads[fileName] = fileWriter.finalize());
}
} else {
deferred.notify({done: offset + limit, total: size});

22
app/js/lib/ng_utils.js

@ -182,11 +182,13 @@ angular.module('izhukov.utils', []) @@ -182,11 +182,13 @@ angular.module('izhukov.utils', [])
return 'data:' + mimeType + ';base64,' + bytesToBase64(fileData);
}
function downloadFile (url, mimeType, fileName) {
// if (Config.Mobile) {
// window.open(url, '_blank');
// return;
// }
function downloadFile (blob, mimeType, fileName) {
if (window.navigator && navigator.msSaveBlob !== undefined) {
window.navigator.msSaveBlob(blob, fileName);
}
var url = getUrl(blob, mimeType);
var anchor = $('<a>Download</a>')
.css({position: 'absolute', top: 1, left: 1})
.attr('href', url)
@ -194,8 +196,14 @@ angular.module('izhukov.utils', []) @@ -194,8 +196,14 @@ angular.module('izhukov.utils', [])
.attr('download', fileName)
.appendTo('body');
anchor[0].dataset.downloadurl = [mimeType, fileName, url].join(':');
anchor[0].click();
if (anchor[0].dataset) {
anchor[0].dataset.downloadurl = [mimeType, fileName, url].join(':');
}
try {
anchor[0].click();
} catch (e) {
window.open(url, '_blank');
}
$timeout(function () {
anchor.remove();
}, 100);

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

@ -204,6 +204,7 @@ @@ -204,6 +204,7 @@
"error_modal_flood_title": "Too fast",
"error_modal_internal_title": "Server error",
"error_modal_alert": "Alert",
"error_modal_media_not_supported_title": "Unsupported media",
"error_modal_network_description": "Please check your internet connection.",
"error_modal_firstname_invali_description": "The first name you entered is invalid.",
@ -218,6 +219,7 @@ @@ -218,6 +219,7 @@
"error_modal_username_invalid_description": "Sorry, this username is not allowed.",
"error_modal_phonebook_required_description": "Telegram needs access to phonebook to import contacts.",
"error_modal_username_occupied_description": "Sorry, this username is already taken.",
"error_modal_media_not_supported_description": "Your browser cannot play this media file. Try downloading the file and opening it in a standalone player.",
"error_modal_bad_request_description": "One of the params is missing or invalid.",
"error_modal_unauthorized_description": "This action requires authorization access. Please {login-link: log in}.",

41
app/js/services.js

@ -602,7 +602,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -602,7 +602,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
})
.service('AppMessagesManager', function ($q, $rootScope, $location, $filter, ApiUpdatesManager, AppUsersManager, AppChatsManager, AppPeersManager, AppPhotosManager, AppVideoManager, AppDocsManager, AppAudioManager, MtpApiManager, MtpApiFileManager, RichTextProcessor, NotificationsManager, SearchIndexManager, PeersSelectService,Storage, _) {
.service('AppMessagesManager', function ($q, $rootScope, $location, $filter, ApiUpdatesManager, AppUsersManager, AppChatsManager, AppPeersManager, AppPhotosManager, AppVideoManager, AppDocsManager, AppAudioManager, MtpApiManager, MtpApiFileManager, RichTextProcessor, NotificationsManager, SearchIndexManager, PeersSelectService,Storage, FileManager, _) {
var messagesStorage = {};
var messagesForHistory = {};
@ -1883,8 +1883,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1883,8 +1883,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
notification.tag = peerString;
if (notificationPhoto.location && !notificationPhoto.location.empty) {
MtpApiFileManager.downloadSmallFile(notificationPhoto.location, notificationPhoto.size).then(function (url) {
notification.image = url;
MtpApiFileManager.downloadSmallFile(notificationPhoto.location, notificationPhoto.size).then(function (blob) {
notification.image = FileManager.getUrl(blob, 'image/jpeg');
if (message.unread) {
NotificationsManager.notify(notification);
@ -2337,7 +2337,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2337,7 +2337,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
fullPhotoSize.location.dc_id, inputFileLocation, fullPhotoSize.size, {
mime: mimeType,
toFileEntry: writableFileEntry
}).then(function (url) {
}).then(function () {
// console.log('file save done');
}, function (e) {
console.log('photo download failed', e);
@ -2346,8 +2346,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2346,8 +2346,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}, function () {
MtpApiFileManager.downloadFile(
fullPhotoSize.location.dc_id, inputFileLocation, fullPhotoSize.size, {mime: mimeType}
).then(function (url) {
FileManager.download(url, mimeType, fileName);
).then(function (blob) {
FileManager.download(blob, mimeType, fileName);
}, function (e) {
console.log('photo download failed', e);
});
@ -2487,6 +2487,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2487,6 +2487,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function downloadVideo (videoID, toFileEntry) {
var video = videos[videoID],
historyVideo = videosForHistory[videoID] || video || {},
mimeType = video.mime_type || 'video/ogg',
inputFileLocation = {
_: 'inputVideoFileLocation',
id: videoID,
@ -2496,11 +2497,12 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2496,11 +2497,12 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
historyVideo.progress = {enabled: !historyVideo.downloaded, percent: 1, total: video.size};
var downloadPromise = MtpApiFileManager.downloadFile(video.dc_id, inputFileLocation, video.size, {
mime: video.mime_type || 'video/ogg',
mime: mimeType,
toFileEntry: toFileEntry
});
downloadPromise.then(function (url) {
downloadPromise.then(function (blob) {
var url = FileManager.getUrl(blob, mimeType);
delete historyVideo.progress;
historyVideo.url = $sce.trustAsResourceUrl(url);
historyVideo.downloaded = true;
@ -2533,8 +2535,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2533,8 +2535,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
downloadVideo(videoID, writableFileEntry);
}
}, function () {
downloadVideo(videoID).then(function (url) {
FileManager.download(url, mimeType, fileName);
downloadVideo(videoID).then(function (blob) {
FileManager.download(blob, mimeType, fileName);
});
});
}
@ -2606,7 +2608,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2606,7 +2608,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
doc.thumb = thumb;
doc.canDownload = !(window.chrome && chrome.fileSystem && chrome.fileSystem.chooseEntry);
doc.withPreview = doc.canDownload && doc.mime_type.match(/^(image\/|application\/pdf)/) ? 1 : 0;
doc.withPreview = doc.canDownload && doc.mime_type.match(/^(image\/)/) ? 1 : 0;
if (isGif && doc.thumb) {
doc.isSpecial = 'gif';
@ -2654,7 +2656,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2654,7 +2656,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
toFileEntry: toFileEntry
});
downloadPromise.then(function (url) {
downloadPromise.then(function (blob) {
var url = FileManager.getUrl(blob, doc.mime_type);
delete historyDoc.progress;
historyDoc.url = $sce.trustAsResourceUrl(url);
historyDoc.downloaded = true;
@ -2698,8 +2701,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2698,8 +2701,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
downloadDoc(docID, writableFileEntry);
}
}, function () {
downloadDoc(docID).then(function (url) {
FileManager.download(url, doc.mime_type, doc.file_name);
downloadDoc(docID).then(function (blob) {
FileManager.download(blob, doc.mime_type, doc.file_name);
});
});
}
@ -2755,6 +2758,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2755,6 +2758,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function downloadAudio (audioID, toFileEntry) {
var audio = audios[audioID],
historyAudio = audiosForHistory[audioID] || audio || {},
mimeType = audio.mime_type || 'audio/ogg',
inputFileLocation = {
_: 'inputAudioFileLocation',
id: audioID,
@ -2764,11 +2768,12 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2764,11 +2768,12 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
historyAudio.progress = {enabled: !historyAudio.downloaded, percent: 1, total: audio.size};
var downloadPromise = MtpApiFileManager.downloadFile(audio.dc_id, inputFileLocation, audio.size, {
mime: audio.mime_type || 'audio/ogg',
mime: mimeType,
toFileEntry: toFileEntry
});
downloadPromise.then(function (url) {
downloadPromise.then(function (blob) {
var url = FileManager.getUrl(blob, mimeType);
delete historyAudio.progress;
historyAudio.url = $sce.trustAsResourceUrl(url);
historyAudio.downloaded = true;
@ -2801,8 +2806,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2801,8 +2806,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
downloadAudio(audioID, writableFileEntry);
}
}, function () {
downloadAudio(audioID).then(function (url) {
FileManager.download(url, mimeType, fileName);
downloadAudio(audioID).then(function (blob) {
FileManager.download(blob, mimeType, fileName);
});
});
}

2
app/partials/desktop/error_modal.html

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
<div class="modal-body">
<h4 ng-if="error" class="modal_simple_header" ng-switch="error.type">
<span ng-switch-when="MEDIA_TYPE_NOT_SUPPORTED" my-i18n="error_modal_media_not_supported_title"></span>
<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="401" my-i18n="error_modal_unauthorized_title"></span>
@ -35,6 +36,7 @@ @@ -35,6 +36,7 @@
<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_OCCUPIED" my-i18n="error_modal_username_occupied_description"></span>
<span ng-switch-when="MEDIA_TYPE_NOT_SUPPORTED" my-i18n="error_modal_media_not_supported_description"></span>
<div ng-switch-default ng-switch="error.code">

Loading…
Cancel
Save