Supported invite links
This commit is contained in:
parent
31900bdcfd
commit
21f08cd29e
@ -28,7 +28,7 @@ angular.module('myApp', [
|
||||
config(['$locationProvider', '$routeProvider', '$compileProvider', 'StorageProvider', function($locationProvider, $routeProvider, $compileProvider, StorageProvider) {
|
||||
|
||||
$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) {
|
||||
StorageProvider.setPrefix('t_');
|
||||
|
@ -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.updateLink = function (force) {
|
||||
function updateLink (force) {
|
||||
if (force) {
|
||||
$scope.exportedInvite.revoking = true;
|
||||
}
|
||||
AppChatsManager.getChatInviteLink($scope.chatID, force).then(function (link) {
|
||||
$scope.exportedInvite = {link: link};
|
||||
$timeout(function () {
|
||||
$scope.$broadcast('ui_invite_select');
|
||||
}, 100);
|
||||
})['finally'](function () {
|
||||
delete $scope.exportedInvite.revoking;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.updateLink();
|
||||
$scope.revokeLink = function () {
|
||||
ErrorService.confirm({
|
||||
type: 'REVOKE_GROUP_INVITE_LINK'
|
||||
}).then(function () {
|
||||
updateLink(true);
|
||||
})
|
||||
}
|
||||
|
||||
updateLink();
|
||||
|
||||
})
|
||||
|
||||
|
@ -2924,16 +2924,27 @@ angular.module('myApp.directives', ['myApp.filters'])
|
||||
.directive('myCopyField', function () {
|
||||
|
||||
return {
|
||||
scope: {
|
||||
selectEvent: '=myCopyField'
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
function link($scope, element, attrs) {
|
||||
element.attr('readonly', 'true');
|
||||
// element.on('keydown paste', cancelEvent);
|
||||
element[0].readonly = true;
|
||||
element.on('click', function () {
|
||||
this.select();
|
||||
});
|
||||
element[0].readonly = true;
|
||||
|
||||
if ($scope.selectEvent) {
|
||||
$scope.$on($scope.selectEvent, function () {
|
||||
setTimeout(function () {
|
||||
element[0].focus();
|
||||
element[0].select();
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
})
|
||||
|
@ -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_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_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_logout_submit": "Log out",
|
||||
@ -251,6 +253,7 @@
|
||||
"conversation_kicked_user": "removed {user}",
|
||||
"conversation_invited_user_message": "invited user",
|
||||
"conversation_kicked_user_message": "removed user",
|
||||
"conversation_joined_by_link": "joined group",
|
||||
"conversation_message_sent": "sent you a message",
|
||||
|
||||
"conversation_unknown_user": "Somebody",
|
||||
@ -264,6 +267,7 @@
|
||||
"message_service_returned_to_group": "returned to group",
|
||||
"message_service_kicked_user": "removed {user}",
|
||||
"message_service_left_group": "left group",
|
||||
"message_service_joined_by_link": "joined group via invite link",
|
||||
"message_service_unsupported_action": "Unsupported action {action}",
|
||||
|
||||
"error_modal_warning_title": "Warning",
|
||||
@ -286,7 +290,7 @@
|
||||
"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_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_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.",
|
||||
@ -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_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_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",
|
||||
|
@ -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) {
|
||||
return angular.isObject(chats[id]);
|
||||
}
|
||||
@ -777,7 +737,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
getChatPhoto: getChatPhoto,
|
||||
getChatString: getChatString,
|
||||
getChatInviteLink: getChatInviteLink,
|
||||
openInviteLink: openInviteLink,
|
||||
hasChat: hasChat,
|
||||
wrapForFull: wrapForFull,
|
||||
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 messagesForHistory = {};
|
||||
@ -1963,6 +1922,46 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
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) {
|
||||
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,
|
||||
sendOther: sendOther,
|
||||
forwardMessages: forwardMessages,
|
||||
openChatInviteLink: openChatInviteLink,
|
||||
getMessagePeer: getMessagePeer,
|
||||
wrapForDialog: wrapForDialog,
|
||||
wrapForHistory: wrapForHistory,
|
||||
@ -4095,7 +4095,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
// resource path
|
||||
"(?:/(?:\\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 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
|
||||
var contextUrl = !options.noLinks && siteMentions[contextSite];
|
||||
if (match[2] != '@' && contextExternal) {
|
||||
contextUrl = false;
|
||||
}
|
||||
if (contextUrl) {
|
||||
var attr = '';
|
||||
if (options.highlightUsername &&
|
||||
options.highlightUsername.toLowerCase() == match[3].toLowerCase() &&
|
||||
match[2] == '@') {
|
||||
options.highlightUsername.toLowerCase() == match[3].toLowerCase()) {
|
||||
attr = 'class="im_message_mymention"';
|
||||
}
|
||||
html.push(
|
||||
@ -4225,6 +4221,19 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
||||
|
||||
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
|
||||
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 () {
|
||||
if (!$routeParams.tgaddr) {
|
||||
return;
|
||||
var tgAddrRegEx = /^(web\+)?tg:(\/\/)?(.+)/;
|
||||
|
||||
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', {
|
||||
peerString: AppUsersManager.getUserString(userID)
|
||||
});
|
||||
});
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
var matches = $routeParams.tgaddr.match(/^(web\+)?tg:(\/\/)?join\?invite=(.+)$/);
|
||||
if (matches && matches[3]) {
|
||||
AppChatsManager.openInviteLink(matches[3]);
|
||||
if (matches = url.match(/^join\?invite=(.+)$/)) {
|
||||
AppMessagesManager.openChatInviteLink(matches[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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');
|
||||
} 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 {
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
<div class="md-input-group md-textarea-group" my-labeled-input>
|
||||
<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>
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
<div class="md_simple_modal_footer">
|
||||
<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>
|
@ -47,6 +47,12 @@
|
||||
<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="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-when="true" ng-bind="message"></span>
|
||||
<span ng-switch-default my-i18n="confirm_modal_are_u_sure"></span>
|
||||
|
@ -93,6 +93,9 @@
|
||||
<my-i18n-param name="user"><span my-user-link="dialogMessage.action.user_id"></span></my-i18n-param>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span ng-switch-when="messageActionChatJoinedByLink" my-i18n="conversation_joined_by_link"></span>
|
||||
|
||||
</span>
|
||||
|
||||
<span class="im_dialog_message_text" ng-if="dialogMessage.message.length" ng-bind-html="dialogMessage.richMessage"></span>
|
||||
|
@ -38,7 +38,11 @@
|
||||
<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="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">
|
||||
|
@ -18,6 +18,9 @@
|
||||
</span>
|
||||
<span ng-switch-default my-i18n="message_service_left_group"></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>
|
||||
|
@ -102,6 +102,8 @@
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -19,5 +19,9 @@
|
||||
<span ng-switch-default my-i18n="message_service_left_group"></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>
|
||||
|
Loading…
Reference in New Issue
Block a user