Browse Source

Supported invite links

master
Igor Zhukov 10 years ago
parent
commit
21f08cd29e
  1. 2
      app/js/app.js
  2. 17
      app/js/controllers.js
  3. 15
      app/js/directives.js
  4. 8
      app/js/locales/en-us.json
  5. 159
      app/js/services.js
  6. 4
      app/partials/desktop/chat_invite_link_modal.html
  7. 6
      app/partials/desktop/confirm_modal.html
  8. 3
      app/partials/desktop/dialog.html
  9. 6
      app/partials/desktop/error_modal.html
  10. 5
      app/partials/desktop/message_service.html
  11. 2
      app/partials/mobile/dialog.html
  12. 6
      app/partials/mobile/message_service.html

2
app/js/app.js

@ -28,7 +28,7 @@ angular.module('myApp', [
config(['$locationProvider', '$routeProvider', '$compileProvider', 'StorageProvider', function($locationProvider, $routeProvider, $compileProvider, StorageProvider) { config(['$locationProvider', '$routeProvider', '$compileProvider', 'StorageProvider', function($locationProvider, $routeProvider, $compileProvider, StorageProvider) {
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|blob|filesystem|chrome-extension|app):|data:image\//); $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|blob|filesystem|chrome-extension|app):|data:image\//);
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|file|mailto|blob|filesystem|chrome-extension|app):|data:/); $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|file|tg|mailto|blob|filesystem|chrome-extension|app):|data:/);
if (Config.Modes.test) { if (Config.Modes.test) {
StorageProvider.setPrefix('t_'); StorageProvider.setPrefix('t_');

17
app/js/controllers.js

@ -3618,22 +3618,33 @@ angular.module('myApp.controllers', ['myApp.i18n'])
}; };
}) })
.controller('ChatInviteLinkModalController', function (_, $scope, $modalInstance, AppChatsManager) { .controller('ChatInviteLinkModalController', function (_, $scope, $timeout, $modalInstance, AppChatsManager, ErrorService) {
$scope.exportedInvite = {link: _('group_invite_link_loading_raw')}; $scope.exportedInvite = {link: _('group_invite_link_loading_raw')};
$scope.updateLink = function (force) { function updateLink (force) {
if (force) { if (force) {
$scope.exportedInvite.revoking = true; $scope.exportedInvite.revoking = true;
} }
AppChatsManager.getChatInviteLink($scope.chatID, force).then(function (link) { AppChatsManager.getChatInviteLink($scope.chatID, force).then(function (link) {
$scope.exportedInvite = {link: link}; $scope.exportedInvite = {link: link};
$timeout(function () {
$scope.$broadcast('ui_invite_select');
}, 100);
})['finally'](function () { })['finally'](function () {
delete $scope.exportedInvite.revoking; delete $scope.exportedInvite.revoking;
}); });
} }
$scope.updateLink(); $scope.revokeLink = function () {
ErrorService.confirm({
type: 'REVOKE_GROUP_INVITE_LINK'
}).then(function () {
updateLink(true);
})
}
updateLink();
}) })

15
app/js/directives.js

@ -2924,16 +2924,27 @@ angular.module('myApp.directives', ['myApp.filters'])
.directive('myCopyField', function () { .directive('myCopyField', function () {
return { return {
scope: {
selectEvent: '=myCopyField'
},
link: link link: link
}; };
function link($scope, element, attrs) { function link($scope, element, attrs) {
element.attr('readonly', 'true'); element.attr('readonly', 'true');
// element.on('keydown paste', cancelEvent); element[0].readonly = true;
element.on('click', function () { element.on('click', function () {
this.select(); this.select();
}); });
element[0].readonly = true;
if ($scope.selectEvent) {
$scope.$on($scope.selectEvent, function () {
setTimeout(function () {
element[0].focus();
element[0].select();
}, 100);
});
}
}; };
}) })

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

@ -189,6 +189,8 @@
"confirm_modal_recovery_email_empty_md": "Warning! Are you sure you don't want to add a password recovery e-mail?\n\nIf you forget your password, you will lose access to your Telegram account", "confirm_modal_recovery_email_empty_md": "Warning! Are you sure you don't want to add a password recovery e-mail?\n\nIf you forget your password, you will lose access to your Telegram account",
"confirm_modal_abort_password_setup": "Abort two-step verification setup?", "confirm_modal_abort_password_setup": "Abort two-step verification setup?",
"confirm_modal_reset_account_md": "Are you sure?\nThis action can not be undone.\n\nYou will lose all your chats and messages, along with any media and files you shared, if you proceed with resetting your account.", "confirm_modal_reset_account_md": "Are you sure?\nThis action can not be undone.\n\nYou will lose all your chats and messages, along with any media and files you shared, if you proceed with resetting your account.",
"confirm_modal_join_group_link": "Do you want to join the group «{title}»?",
"confirm_modal_revoke_group_link": "Are you sure you want to revoke this link? Once you do, no one will be able to join the group using it.",
"confirm_modal_are_u_sure": "Are you sure?", "confirm_modal_are_u_sure": "Are you sure?",
"confirm_modal_logout_submit": "Log out", "confirm_modal_logout_submit": "Log out",
@ -251,6 +253,7 @@
"conversation_kicked_user": "removed {user}", "conversation_kicked_user": "removed {user}",
"conversation_invited_user_message": "invited user", "conversation_invited_user_message": "invited user",
"conversation_kicked_user_message": "removed user", "conversation_kicked_user_message": "removed user",
"conversation_joined_by_link": "joined group",
"conversation_message_sent": "sent you a message", "conversation_message_sent": "sent you a message",
"conversation_unknown_user": "Somebody", "conversation_unknown_user": "Somebody",
@ -264,6 +267,7 @@
"message_service_returned_to_group": "returned to group", "message_service_returned_to_group": "returned to group",
"message_service_kicked_user": "removed {user}", "message_service_kicked_user": "removed {user}",
"message_service_left_group": "left group", "message_service_left_group": "left group",
"message_service_joined_by_link": "joined group via invite link",
"message_service_unsupported_action": "Unsupported action {action}", "message_service_unsupported_action": "Unsupported action {action}",
"error_modal_warning_title": "Warning", "error_modal_warning_title": "Warning",
@ -286,7 +290,7 @@
"error_modal_firstname_invali_description": "The first name you entered is invalid.", "error_modal_firstname_invali_description": "The first name you entered is invalid.",
"error_modal_lastname_invalid_description": "The last name you entered is invalid.", "error_modal_lastname_invalid_description": "The last name you entered is invalid.",
"error_modal_phone_invalid_description": "The phone number you entered is invalid.", "error_modal_phone_invalid_description": "The phone number you entered is invalid.",
"error_modal_users_too_much_description": "You have selected too much users.", "error_modal_users_too_much_description": "Too many group members.",
"error_modal_photo_dimensions_invalid_description": "The photo dimensions are invalid, please select another file.", "error_modal_photo_dimensions_invalid_description": "The photo dimensions are invalid, please select another file.",
"error_modal_video_file_invalid_description": "The video file extension is invalid or unsupported, please select another file.", "error_modal_video_file_invalid_description": "The video file extension is invalid or unsupported, please select another file.",
"error_modal_photo_too_small_description": "The photo you provided is too small.", "error_modal_photo_too_small_description": "The photo you provided is too small.",
@ -309,6 +313,8 @@
"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_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_success_descripion": "Your password for Two-Step Verification is now active.",
"error_modal_password_disabled_descripion": "You have disabled Two-Step Verification.", "error_modal_password_disabled_descripion": "You have disabled Two-Step Verification.",
"error_modal_user_not_mutual_contact": "The user can be invited by his contact only",
"error_modal_invite_link_invalid": "The invite link is invalid",
"head_telegram": "Telegram", "head_telegram": "Telegram",

159
app/js/services.js

@ -617,46 +617,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}); });
} }
function openInviteLink (hash) {
return MtpApiManager.invokeApi('messages.checkChatInvite', {
hash: hash
}).then(function (chatInvite) {
var chatTitle;
if (chatInvite._ == 'chatInviteAlready') {
saveApiChat(chatInvite.chat);
if (!chatInvite.chat.left) {
return $rootScope.$broadcast('history_focus', {
peerString: getChatString(chatInvite.chat.id)
});
}
chatTitle = chatInvite.chat.title;
} else {
chatTitle = chatInvite.title;
}
ErrorService.confirm({
type: 'JOIN_GROUP_BY_LINK',
title: chatTitle
}).then(function () {
return MtpApiManager.invokeApi('messages.importChatInvite', {
hash: hash
}).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
if (updates.updates && updates.updates.length) {
for (var i = 0, len = updates.updates.length, update; i < len; i++) {
update = updates.updates[i];
if (update._ == 'updateNewMessage') {
$rootScope.$broadcast('history_focus', {peerString: AppChatsManager.getChatString(update.message.to_id.chat_id)
});
break;
}
}
}
});
});
});
}
function hasChat (id) { function hasChat (id) {
return angular.isObject(chats[id]); return angular.isObject(chats[id]);
} }
@ -777,7 +737,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
getChatPhoto: getChatPhoto, getChatPhoto: getChatPhoto,
getChatString: getChatString, getChatString: getChatString,
getChatInviteLink: getChatInviteLink, getChatInviteLink: getChatInviteLink,
openInviteLink: openInviteLink,
hasChat: hasChat, hasChat: hasChat,
wrapForFull: wrapForFull, wrapForFull: wrapForFull,
openChat: openChat openChat: openChat
@ -853,7 +812,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} }
}) })
.service('AppMessagesManager', function ($q, $rootScope, $location, $filter, $timeout, $sce, ApiUpdatesManager, AppUsersManager, AppChatsManager, AppPeersManager, AppPhotosManager, AppVideoManager, AppDocsManager, AppAudioManager, AppWebPagesManager, MtpApiManager, MtpApiFileManager, RichTextProcessor, NotificationsManager, PeersSelectService, Storage, FileManager, TelegramMeWebService, StatusManager, _) { .service('AppMessagesManager', function ($q, $rootScope, $location, $filter, $timeout, $sce, ApiUpdatesManager, AppUsersManager, AppChatsManager, AppPeersManager, AppPhotosManager, AppVideoManager, AppDocsManager, AppAudioManager, AppWebPagesManager, MtpApiManager, MtpApiFileManager, RichTextProcessor, NotificationsManager, PeersSelectService, Storage, FileManager, TelegramMeWebService, ErrorService, StatusManager, _) {
var messagesStorage = {}; var messagesStorage = {};
var messagesForHistory = {}; var messagesForHistory = {};
@ -1963,6 +1922,46 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return false; return false;
} }
function openChatInviteLink (hash) {
return MtpApiManager.invokeApi('messages.checkChatInvite', {
hash: hash
}).then(function (chatInvite) {
var chatTitle;
if (chatInvite._ == 'chatInviteAlready') {
AppChatsManager.saveApiChat(chatInvite.chat);
if (!chatInvite.chat.left) {
return $rootScope.$broadcast('history_focus', {
peerString: AppChatsManager.getChatString(chatInvite.chat.id)
});
}
chatTitle = chatInvite.chat.title;
} else {
chatTitle = chatInvite.title;
}
ErrorService.confirm({
type: 'JOIN_GROUP_BY_LINK',
title: chatTitle
}).then(function () {
return MtpApiManager.invokeApi('messages.importChatInvite', {
hash: hash
}).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
if (updates.updates && updates.updates.length) {
for (var i = 0, len = updates.updates.length, update; i < len; i++) {
update = updates.updates[i];
if (update._ == 'updateNewMessage') {
$rootScope.$broadcast('history_focus', {peerString: AppChatsManager.getChatString(update.message.to_id.chat_id)
});
break;
}
}
}
});
});
});
}
function getMessagePeer (message) { function getMessagePeer (message) {
var toID = message.to_id && AppPeersManager.getPeerID(message.to_id) || 0; var toID = message.to_id && AppPeersManager.getPeerID(message.to_id) || 0;
@ -2682,6 +2681,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
sendFile: sendFile, sendFile: sendFile,
sendOther: sendOther, sendOther: sendOther,
forwardMessages: forwardMessages, forwardMessages: forwardMessages,
openChatInviteLink: openChatInviteLink,
getMessagePeer: getMessagePeer, getMessagePeer: getMessagePeer,
wrapForDialog: wrapForDialog, wrapForDialog: wrapForDialog,
wrapForHistory: wrapForHistory, wrapForHistory: wrapForHistory,
@ -4095,7 +4095,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
// resource path // resource path
"(?:/(?:\\S{0,255}[^\\s.;,(\\[\\]{}<>\"'])?)?"; "(?:/(?:\\S{0,255}[^\\s.;,(\\[\\]{}<>\"'])?)?";
var regExp = new RegExp('(^|\\s)((?:https?://)?telegram\\.me/|@)([a-zA-Z\\d_]{5,32})|(' + urlRegex + ')|(\\n)|(' + emojiRegex + ')|(^|\\s)(#[' + regexAlphaNumericChars + ']{2,64})', 'i'); var regExp = new RegExp('(^|\\s)(@)([a-zA-Z\\d_]{5,32})|(' + urlRegex + ')|(\\n)|(' + emojiRegex + ')|(^|\\s)(#[' + regexAlphaNumericChars + ']{2,64})', 'i');
var emailRegex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; var emailRegex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var youtubeRegex = /^(?:https?:\/\/)?(?:www\.)?youtu(?:|\.be|be\.com|\.b)(?:\/v\/|\/watch\\?v=|e\/|(?:\/\??#)?\/watch(?:.+)v=)(.{11})(?:\&[^\s]*)?/; var youtubeRegex = /^(?:https?:\/\/)?(?:www\.)?youtu(?:|\.be|be\.com|\.b)(?:\/v\/|\/watch\\?v=|e\/|(?:\/\??#)?\/watch(?:.+)v=)(.{11})(?:\&[^\s]*)?/;
@ -4166,14 +4166,10 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
if (match[3]) { // telegram.me links if (match[3]) { // telegram.me links
var contextUrl = !options.noLinks && siteMentions[contextSite]; var contextUrl = !options.noLinks && siteMentions[contextSite];
if (match[2] != '@' && contextExternal) {
contextUrl = false;
}
if (contextUrl) { if (contextUrl) {
var attr = ''; var attr = '';
if (options.highlightUsername && if (options.highlightUsername &&
options.highlightUsername.toLowerCase() == match[3].toLowerCase() && options.highlightUsername.toLowerCase() == match[3].toLowerCase()) {
match[2] == '@') {
attr = 'class="im_message_mymention"'; attr = 'class="im_message_mymention"';
} }
html.push( html.push(
@ -4225,6 +4221,19 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
url = (match[5] ? '' : protocol) + match[4]; url = (match[5] ? '' : protocol) + match[4];
} }
var tgMeMatch;
if (tld == 'me' &&
(tgMeMatch = url.match(/^https?:\/\/telegram\.me\/(.+)/))) {
var path = tgMeMatch[1].split('/');
switch (path[0]) {
case 'joinchat':
url = 'tg://join?invite=' + path[1];
break;
default:
url = 'tg://resolve?domain=' + path[0];
}
}
} else { // IP address } else { // IP address
url = (match[5] ? '' : 'http://') + match[4]; url = (match[5] ? '' : 'http://') + match[4];
} }
@ -5269,26 +5278,37 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}) })
.service('LocationParamsService', function ($rootScope, $routeParams, AppUsersManager, AppChatsManager) { .service('LocationParamsService', function ($rootScope, $routeParams, AppUsersManager, AppMessagesManager) {
function checkTgAddr () { var tgAddrRegEx = /^(web\+)?tg:(\/\/)?(.+)/;
if (!$routeParams.tgaddr) {
return; function checkLocationTgAddr () {
if ($routeParams.tgaddr) {
var matches = $routeParams.tgaddr.match(tgAddrRegEx);
if (matches) {
handleTgProtoAddr(matches[3]);
} }
var matches = $routeParams.tgaddr.match(/^(web\+)?tg:(\/\/)?resolve\?domain=(.+)$/); }
if (matches && matches[3]) { }
AppUsersManager.resolveUsername(matches[3]).then(function (userID) {
function handleTgProtoAddr (url) {
var matches;
if (matches = url.match(/^resolve\?domain=(.+)$/)) {
AppUsersManager.resolveUsername(matches[1]).then(function (userID) {
$rootScope.$broadcast('history_focus', { $rootScope.$broadcast('history_focus', {
peerString: AppUsersManager.getUserString(userID) peerString: AppUsersManager.getUserString(userID)
}); });
}); });
return; return true;
} }
var matches = $routeParams.tgaddr.match(/^(web\+)?tg:(\/\/)?join\?invite=(.+)$/); if (matches = url.match(/^join\?invite=(.+)$/)) {
if (matches && matches[3]) { AppMessagesManager.openChatInviteLink(matches[1]);
AppChatsManager.openInviteLink(matches[3]); return true;
} }
return false;
} }
var started = !('registerProtocolHandler' in navigator); var started = !('registerProtocolHandler' in navigator);
@ -5304,8 +5324,25 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
navigator.registerProtocolHandler('web+tg', '#im?tgaddr=%s', 'Telegram Web'); navigator.registerProtocolHandler('web+tg', '#im?tgaddr=%s', 'Telegram Web');
} catch (e) {} } catch (e) {}
$rootScope.$on('$routeUpdate', checkTgAddr);
checkTgAddr(); $(document).on('click', function (event) {
var target = event.target;
if (target &&
target.tagName == 'A' &&
!target.onclick &&
!target.onmousedown) {
var href = $(target).attr('href') || target.href || '';
var match = href.match(tgAddrRegEx);
if (match) {
if (handleTgProtoAddr(match[3])) {
return cancelEvent(event);
}
}
}
});
$rootScope.$on('$routeUpdate', checkLocationTgAddr);
checkLocationTgAddr();
}; };
return { return {

4
app/partials/desktop/chat_invite_link_modal.html

@ -8,7 +8,7 @@
<div class="md-input-group md-textarea-group" my-labeled-input> <div class="md-input-group md-textarea-group" my-labeled-input>
<label class="md-input-label" my-i18n="group_invite_link_link_label"></label> <label class="md-input-label" my-i18n="group_invite_link_link_label"></label>
<textarea class="md-input" ng-model="exportedInvite.link" rows="2" my-copy-field></textarea> <textarea class="md-input" ng-model="exportedInvite.link" rows="2" my-copy-field="'ui_invite_select'"></textarea>
</div> </div>
</div> </div>
@ -17,7 +17,7 @@
<div class="md_simple_modal_footer"> <div class="md_simple_modal_footer">
<button class="btn btn-md" ng-click="$dismiss()" my-i18n="modal_cancel"></button> <button class="btn btn-md" ng-click="$dismiss()" my-i18n="modal_cancel"></button>
<button class="btn btn-md btn-md-primary" ng-class="{disabled: exportedInvite.revoking}" ng-click="updateLink(true)" ng-bind="exportedInvite.revoking ? 'group_invite_revoke_active' : 'group_invite_revoke' | i18n" ng-disabled="exportedInvite.revoking"></button> <button class="btn btn-md btn-md-primary" ng-class="{disabled: exportedInvite.revoking}" ng-click="revokeLink()" ng-bind="exportedInvite.revoking ? 'group_invite_revoke_active' : 'group_invite_revoke' | i18n" ng-disabled="exportedInvite.revoking"></button>
</div> </div>
</div> </div>

6
app/partials/desktop/confirm_modal.html

@ -47,6 +47,12 @@
<div ng-switch-when="RECOVERY_EMAIL_EMPTY" my-i18n="confirm_modal_recovery_email_empty_md"></div> <div ng-switch-when="RECOVERY_EMAIL_EMPTY" my-i18n="confirm_modal_recovery_email_empty_md"></div>
<div ng-switch-when="PASSWORD_ABORT_SETUP" my-i18n="confirm_modal_abort_password_setup"></div> <div ng-switch-when="PASSWORD_ABORT_SETUP" my-i18n="confirm_modal_abort_password_setup"></div>
<div ng-switch-when="RESET_ACCOUNT" my-i18n="confirm_modal_reset_account_md"></div> <div ng-switch-when="RESET_ACCOUNT" my-i18n="confirm_modal_reset_account_md"></div>
<div ng-switch-when="JOIN_GROUP_BY_LINK" my-i18n="confirm_modal_join_group_link">
<my-i18n-param name="title"><strong ng-bind="title"></strong></my-i18n-param>
</div>
<div ng-switch-when="REVOKE_GROUP_INVITE_LINK" my-i18n="confirm_modal_revoke_group_link"></div>
<span ng-switch-default ng-switch="message.length > 0"> <span ng-switch-default ng-switch="message.length > 0">
<span ng-switch-when="true" ng-bind="message"></span> <span ng-switch-when="true" ng-bind="message"></span>
<span ng-switch-default my-i18n="confirm_modal_are_u_sure"></span> <span ng-switch-default my-i18n="confirm_modal_are_u_sure"></span>

3
app/partials/desktop/dialog.html

@ -93,6 +93,9 @@
<my-i18n-param name="user"><span my-user-link="dialogMessage.action.user_id"></span></my-i18n-param> <my-i18n-param name="user"><span my-user-link="dialogMessage.action.user_id"></span></my-i18n-param>
</span> </span>
</span> </span>
<span ng-switch-when="messageActionChatJoinedByLink" my-i18n="conversation_joined_by_link"></span>
</span> </span>
<span class="im_dialog_message_text" ng-if="dialogMessage.message.length" ng-bind-html="dialogMessage.richMessage"></span> <span class="im_dialog_message_text" ng-if="dialogMessage.message.length" ng-bind-html="dialogMessage.richMessage"></span>

6
app/partials/desktop/error_modal.html

@ -38,7 +38,11 @@
<span ng-switch-when="USERNAME_OCCUPIED" my-i18n="error_modal_username_occupied_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> <span ng-switch-when="MEDIA_TYPE_NOT_SUPPORTED" my-i18n="error_modal_media_not_supported_description"></span>
<span ng-switch-when="USERNAME_NOT_OCCUPIED" my-i18n="error_modal_username_not_found_description"></span> <span ng-switch-when="USERNAME_NOT_OCCUPIED" my-i18n="error_modal_username_not_found_description"></span>
<span ng-switch-when="PASSWORD_RECOVERY_NA" my-i18n="error_modal_recovery_na_description"></span> <span ng-switch-when="USER_NOT_MUTUAL_CONTACT" my-i18n="error_modal_user_not_mutual_contact"></span>
<span ng-switch-when="INVITE_HASH_INVALID" my-i18n="error_modal_invite_link_invalid"></span>
<span ng-switch-when="INVITE_HASH_EXPIRED" my-i18n="error_modal_invite_link_invalid"></span>
<span ng-switch-when="INVITE_HASH_EMPTY" my-i18n="error_modal_invite_link_invalid"></span>
<div ng-switch-default ng-switch="error.code"> <div ng-switch-default ng-switch="error.code">

5
app/partials/desktop/message_service.html

@ -18,6 +18,9 @@
</span> </span>
<span ng-switch-default my-i18n="message_service_left_group"></span> <span ng-switch-default my-i18n="message_service_left_group"></span>
</span> </span>
<span ng-switch-when="messageActionChatJoinedByLink" my-i18n="message_service_joined_by_link"></span>
<span ng-switch-default ng-bind="'message_service_unsupported_action' | i18n:historyMessage.action._"></span> <span ng-switch-default my-i18n="message_service_unsupported_action">
<my-i18n-param name="action"><span ng-bind="historyMessage.action._"></span></my-i18n-param>
</span>
</span> </span>

2
app/partials/mobile/dialog.html

@ -102,6 +102,8 @@
</span> </span>
</span> </span>
<span ng-switch-when="messageActionChatJoinedByLink" my-i18n="conversation_joined_by_link"></span>
<span class="im_dialog_message_text" ng-if="dialogMessage.message.length" ng-bind-html="dialogMessage.richMessage"></span> <span class="im_dialog_message_text" ng-if="dialogMessage.message.length" ng-bind-html="dialogMessage.richMessage"></span>
</div> </div>
</div> </div>

6
app/partials/mobile/message_service.html

@ -19,5 +19,9 @@
<span ng-switch-default my-i18n="message_service_left_group"></span> <span ng-switch-default my-i18n="message_service_left_group"></span>
</span> </span>
<span ng-switch-default ng-bind="'message_service_unsupported_action' | i18n:historyMessage.action._"></span> <span ng-switch-when="messageActionChatJoinedByLink" my-i18n="message_service_joined_by_link"></span>
<span ng-switch-default my-i18n="message_service_unsupported_action">
<my-i18n-param name="action"><span ng-bind="historyMessage.action._"></span></my-i18n-param>
</span>
</span> </span>

Loading…
Cancel
Save