Channels improvements

Supported load important history
Added channel profile
This commit is contained in:
Igor Zhukov 2015-09-28 23:25:55 +03:00
parent 5aa5a1d9a2
commit b0b5e2c75c
18 changed files with 800 additions and 161 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -706,7 +706,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.$on('history_delete', function (e, historyUpdate) {
for (var i = 0; i < $scope.dialogs.length; i++) {
if ($scope.dialogs[i].peerID == historyUpdate.peerID) {
if (historyUpdate.msgs[$scope.dialogs[i].id]) {
if (historyUpdate.msgs[$scope.dialogs[i].mid]) {
$scope.dialogs[i].deleted = true;
}
break;
@ -1490,7 +1490,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
i, startPos, curMessageID;
for (i = 0; i < peerHistory.messages.length; i++) {
if (peerHistory.messages[i].id == lastSelectID) {
if (peerHistory.messages[i].mid == lastSelectID) {
startPos = i;
break;
}
@ -1498,7 +1498,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
i = startPos;
while (peerHistory.messages[i] &&
(curMessageID = peerHistory.messages[i].id) != messageID) {
(curMessageID = peerHistory.messages[i].mid) != messageID) {
if (!$scope.selectedMsgs[curMessageID]) {
$scope.selectedMsgs[curMessageID] = true;
$scope.selectedCount++;
@ -1646,7 +1646,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
return;
}
AppMessagesManager.sendText(peerID, button.text, {
replyToMsgID: peerID < 0 && replyKeyboard.id
replyToMsgID: peerID < 0 && replyKeyboard.mid
});
});
@ -1700,7 +1700,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
!historyMessage.out &&
!(history.messages[history.messages.length - 2] || {}).unread) {
$scope.historyUnreadAfter = historyMessage.id;
$scope.historyUnreadAfter = historyMessage.mid;
unreadAfterIdle = true;
$scope.$broadcast('messages_unread_after');
}
@ -1740,7 +1740,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
if (len > 10) {
if (curPeer) {
if (exlen > 10) {
minID = history.messages[exlen - 1].id;
minID = history.messages[exlen - 1].mid;
$scope.historyState.skipped = hasLess = minID > 0;
if (hasLess) {
loadAfterSync = peerID;
@ -1825,7 +1825,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
i;
for (i = 0; i < history.messages.length; i++) {
if (!historyUpdate.msgs[history.messages[i].id]) {
if (!historyUpdate.msgs[history.messages[i].mid]) {
newMessages.push(history.messages[i]);
}
};
@ -1949,7 +1949,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
var timeout = 0;
var options = {
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.id
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.mid
};
do {
@ -2074,7 +2074,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
var message = $scope.draftMessage.replyToMessage;
if (message &&
$scope.historyState.replyKeyboard &&
$scope.historyState.replyKeyboard.id == message.id &&
$scope.historyState.replyKeyboard.mid == message.mid &&
!$scope.historyState.replyKeyboard.pFlags.hidden) {
$scope.historyState.replyKeyboard.pFlags.hidden = true;
$scope.$broadcast('ui_keyboard_update');
@ -2110,7 +2110,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
(replyKeyboard._ == 'replyKeyboardMarkup' && peerID < 0));
if (addReplyMessage) {
replySelect(replyKeyboard.id);
replySelect(replyKeyboard.mid);
replyToMarkup = true;
}
else if (replyToMarkup) {
@ -2162,7 +2162,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
return;
}
var options = {
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.id,
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.mid,
isMedia: $scope.draftMessage.isMedia
};
@ -2196,7 +2196,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
}
}
var options = {
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.id
replyToMsgID: $scope.draftMessage.replyToMessage && $scope.draftMessage.replyToMessage.mid
};
AppMessagesManager.sendOther($scope.curDialog.peerID, inputMedia, options);
$scope.$broadcast('ui_message_send');
@ -2647,15 +2647,18 @@ angular.module('myApp.controllers', ['myApp.i18n'])
})
.controller('ChatpicModalController', function ($q, $scope, $rootScope, $modalInstance, MtpApiManager, AppPhotosManager, AppChatsManager, AppPeersManager, AppMessagesManager, PeersSelectService, ErrorService) {
.controller('ChatpicModalController', function ($q, $scope, $rootScope, $modalInstance, MtpApiManager, AppPhotosManager, AppChatsManager, AppPeersManager, AppMessagesManager, ApiUpdatesManager, PeersSelectService, ErrorService) {
$scope.photo = AppPhotosManager.wrapForFull($scope.photoID);
$scope.photo.thumb = {
location: AppPhotosManager.choosePhotoSize($scope.photo, 0, 0).location
};
var chat = AppChatsManager.getChat($scope.chatID);
var isChannel = AppChatsManager.isChannel($scope.chatID);
$scope.canForward = true;
$scope.canDelete = true;
$scope.canDelete = isChannel ? chat.pFlags.creator : true;
$scope.forward = function () {
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) {
@ -2679,10 +2682,19 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope['delete'] = function () {
ErrorService.confirm({type: 'PHOTO_DELETE'}).then(function () {
$scope.photo.updating = true;
MtpApiManager.invokeApi('messages.editChatPhoto', {
chat_id: AppChatsManager.getChatInput($scope.chatID),
photo: {_: 'inputChatPhotoEmpty'}
}).then(function (updates) {
var apiPromise;
if (AppChatsManager.isChannel($scope.chatID)) {
apiPromise = MtpApiManager.invokeApi('channels.editPhoto', {
channel: AppChatsManager.getChannelInput($scope.chatID),
photo: {_: 'inputChatPhotoEmpty'}
});
} else {
apiPromise = MtpApiManager.invokeApi('messages.editChatPhoto', {
chat_id: AppChatsManager.getChatInput($scope.chatID),
photo: {_: 'inputChatPhotoEmpty'}
});
}
apiPromise.then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
$modalInstance.dismiss();
$rootScope.$broadcast('history_focus', {peerString: AppChatsManager.getChatString($scope.chatID)});
@ -3069,6 +3081,150 @@ angular.module('myApp.controllers', ['myApp.i18n'])
})
.controller('ChannelModalController', function ($scope, $timeout, $rootScope, $modal, AppUsersManager, AppChatsManager, AppPhotosManager, MtpApiManager, MtpApiFileManager, NotificationsManager, AppMessagesManager, AppPeersManager, ApiUpdatesManager, ContactsSelectService, ErrorService) {
$scope.chatFull = AppChatsManager.wrapForFull($scope.chatID, {});
$scope.settings = {notifications: true};
AppChatsManager.getChannelFull($scope.chatID, true).then(function (chatFull) {
$scope.chatFull = AppChatsManager.wrapForFull($scope.chatID, chatFull);
$scope.$broadcast('ui_height');
NotificationsManager.savePeerSettings(-$scope.chatID, chatFull.notify_settings);
NotificationsManager.getPeerMuted(-$scope.chatID).then(function (muted) {
$scope.settings.notifications = !muted;
$scope.$watch('settings.notifications', function(newValue, oldValue) {
if (newValue === oldValue) {
return false;
}
NotificationsManager.getPeerSettings(-$scope.chatID).then(function (settings) {
if (newValue) {
settings.mute_until = 0;
} else {
settings.mute_until = 2000000000;
}
NotificationsManager.updatePeerSettings(-$scope.chatID, settings);
});
});
});
});
function onChatUpdated (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
$rootScope.$broadcast('history_focus', {peerString: $scope.chatFull.peerString});
}
$scope.leaveChannel = function () {
MtpApiManager.invokeApi('channels.leaveChannel', {
channel: AppChatsManager.getChannelInput($scope.chatID)
}).then(onChatUpdated);
};
$scope.deleteChannel = function () {
return ErrorService.confirm({type: 'CHANNEL_DELETE'}).then(function () {
MtpApiManager.invokeApi('channels.deleteChannel', {
channel: AppChatsManager.getChannelInput($scope.chatID)
}).then(onChatUpdated);
});
}
$scope.joinChannel = function () {
MtpApiManager.invokeApi('channels.joinChannel', {
channel: AppChatsManager.getChannelInput($scope.chatID)
}).then(onChatUpdated);
};
$scope.inviteToChannel = function () {
var disabled = [];
angular.forEach(($scope.chatFull.participants || {}).participants || [], function(participant){
disabled.push(participant.user_id);
});
ContactsSelectService.selectContacts({disabled: disabled}).then(function (userIDs) {
var inputUsers = [];
angular.forEach(userIDs, function (userID) {
inputUsers.push(AppUsersManager.getUserInput(userID));
});
MtpApiManager.invokeApi('channels.inviteToChannel', {
channel: AppChatsManager.getChannelInput($scope.chatID),
users: inputUsers
}).then(onChatUpdated);
});
};
$scope.kickFromChannel = function (userID) {
MtpApiManager.invokeApi('channels.kickFromChannel', {
channel: AppChatsManager.getChannelInput($scope.chatID),
user_id: AppUsersManager.getUserInput(userID),
kicked: true
}).then(onChatUpdated);
};
$scope.shareLink = function ($event) {
var scope = $rootScope.$new();
scope.chatID = $scope.chatID;
$modal.open({
templateUrl: templateUrl('chat_invite_link_modal'),
controller: 'ChatInviteLinkModalController',
scope: scope,
windowClass: 'md_simple_modal_window'
});
return cancelEvent($event);
}
$scope.photo = {};
$scope.$watch('photo.file', onPhotoSelected);
function onPhotoSelected (photo) {
if (!photo || !photo.type || photo.type.indexOf('image') !== 0) {
return;
}
$scope.photo.updating = true;
MtpApiFileManager.uploadFile(photo).then(function (inputFile) {
return MtpApiManager.invokeApi('channels.editPhoto', {
channel: AppChatsManager.getChannelInput($scope.chatID),
photo: {
_: 'inputChatUploadedPhoto',
file: inputFile,
crop: {_: 'inputPhotoCropAuto'}
}
}).then(onChatUpdated);
})['finally'](function () {
$scope.photo.updating = false;
});
};
$scope.deletePhoto = function () {
$scope.photo.updating = true;
MtpApiManager.invokeApi('messages.editChatPhoto', {
channel: AppChatsManager.getChannelInput($scope.chatID),
photo: {_: 'inputChatPhotoEmpty'}
}).then(onChatUpdated)['finally'](function () {
$scope.photo.updating = false;
});
};
$scope.editChannel = function () {
var scope = $rootScope.$new();
scope.chatID = $scope.chatID;
$modal.open({
templateUrl: templateUrl('channel_edit_modal'),
controller: 'ChannelEditModalController',
scope: scope,
windowClass: 'md_simple_modal_window mobile_modal'
});
}
})
.controller('SettingsModalController', function ($rootScope, $scope, $timeout, $modal, AppUsersManager, AppChatsManager, AppPhotosManager, MtpApiManager, Storage, NotificationsManager, MtpApiFileManager, PasswordManager, ApiUpdatesManager, ChangelogNotifyService, LayoutSwitchService, AppRuntimeManager, ErrorService, _) {
$scope.profile = {};
@ -3911,12 +4067,21 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.group.updating = true;
return MtpApiManager.invokeApi('messages.editChatTitle', {
chat_id: AppChatsManager.getChatInput($scope.chatID),
title: $scope.group.name
}).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
var apiPromise;
if (AppChatsManager.isChannel($scope.chatID)) {
apiPromise = MtpApiManager.invokeApi('channels.editTitle', {
channel: AppChatsManager.getChannelInput($scope.chatID),
title: $scope.group.name
});
} else {
apiPromise = MtpApiManager.invokeApi('messages.editChatTitle', {
chat_id: AppChatsManager.getChatInput($scope.chatID),
title: $scope.group.name
});
}
return apiPromise.then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
var peerString = AppChatsManager.getChatString($scope.chatID);
$rootScope.$broadcast('history_focus', {peerString: peerString});
})['finally'](function () {
@ -3925,19 +4090,80 @@ angular.module('myApp.controllers', ['myApp.i18n'])
};
})
.controller('ChannelEditModalController', function ($q, $scope, $modalInstance, $rootScope, MtpApiManager, AppUsersManager, AppChatsManager, ApiUpdatesManager) {
var channel = AppChatsManager.getChat($scope.chatID);
var initial = {title: channel.title};
$scope.channel = {title: channel.title};
AppChatsManager.getChannelFull($scope.chatID).then(function (channelFull) {
initial.about = channelFull.about;
$scope.channel.about = channelFull.about;
});
$scope.updateChannel = function () {
if (!$scope.channel.title.length) {
return;
}
var promises = [];
if ($scope.channel.title != initial.title) {
promises.push(editTitle());
}
if ($scope.channel.about != initial.about) {
promises.push(editAbout());
}
return $q.all(promises).then(function () {
var peerString = AppChatsManager.getChatString($scope.chatID);
$rootScope.$broadcast('history_focus', {peerString: peerString});
})['finally'](function () {
delete $scope.channel.updating;
});
};
function editTitle () {
return MtpApiManager.invokeApi('channels.editTitle', {
channel: AppChatsManager.getChannelInput($scope.chatID),
title: $scope.channel.title
}).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
});
}
function editAbout () {
return MtpApiManager.invokeApi('channels.editAbout', {
channel: AppChatsManager.getChannelInput($scope.chatID),
about: $scope.channel.about
});
}
})
.controller('ChatInviteLinkModalController', function (_, $scope, $timeout, $modalInstance, AppChatsManager, ErrorService) {
$scope.exportedInvite = {link: _('group_invite_link_loading_raw')};
var isChannel = AppChatsManager.isChannel($scope.chatID);
function selectLink () {
$timeout(function () {
$scope.$broadcast('ui_invite_select');
}, 100);
}
function updateLink (force) {
var chat = AppChatsManager.getChat($scope.chatID);
if (chat.username) {
$scope.exportedInvite = {link: 'https://telegram.me/' + chat.username, short: true};
selectLink();
return;
}
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);
$scope.exportedInvite = {link: link, canRevoke: true};
selectLink();
})['finally'](function () {
delete $scope.exportedInvite.revoking;
});
@ -3945,7 +4171,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.revokeLink = function () {
ErrorService.confirm({
type: 'REVOKE_GROUP_INVITE_LINK'
type: isChannel ? 'REVOKE_CHANNEL_INVITE_LINK' : 'REVOKE_GROUP_INVITE_LINK'
}).then(function () {
updateLink(true);
})

View File

@ -65,7 +65,7 @@ angular.module('myApp.directives', ['myApp.filters'])
needDate = false,
unreadAfter = false,
applySelected = function () {
if (selected != ($scope.selectedMsgs[$scope.historyMessage.id] || false)) {
if (selected != ($scope.selectedMsgs[$scope.historyMessage.mid] || false)) {
selected = !selected;
element.toggleClass(selectedClass, selected);
}
@ -109,7 +109,7 @@ angular.module('myApp.directives', ['myApp.filters'])
$scope.$on('messages_regroup', applyGrouped);
$scope.$on('messages_focus', function (e, focusedMsgID) {
if ((focusedMsgID == $scope.historyMessage.id) != focused) {
if ((focusedMsgID == $scope.historyMessage.mid) != focused) {
focused = !focused;
element.toggleClass(focusClass, focused);
}
@ -122,7 +122,7 @@ angular.module('myApp.directives', ['myApp.filters'])
if ($scope.peerHistory.peerID != $scope.historyPeer.id) {
return;
}
if (unreadAfter != ($scope.historyUnreadAfter == $scope.historyMessage.id)) {
if (unreadAfter != ($scope.historyUnreadAfter == $scope.historyMessage.mid)) {
unreadAfter = !unreadAfter;
if (unreadAfter) {
if (unreadAfterSplit) {
@ -362,10 +362,10 @@ angular.module('myApp.directives', ['myApp.filters'])
if (!message.loading) {
updateMessage($scope, element);
} else {
var messageID = message.id;
var stopWaiting = $scope.$on('messages_downloaded', function (e, msgIDs) {
if (msgIDs.indexOf(messageID) != -1) {
$scope.replyMessage = AppMessagesManager.wrapForDialog(messageID);
var mid = message.mid;
var stopWaiting = $scope.$on('messages_downloaded', function (e, mids) {
if (mids.indexOf(mid) != -1) {
$scope.replyMessage = AppMessagesManager.wrapForDialog(mid);
updateMessage($scope, element);
stopWaiting();
}
@ -379,6 +379,7 @@ angular.module('myApp.directives', ['myApp.filters'])
$(element).remove();
return;
}
console.log(element[0], message, AppPeersManager.getPeer(message.fromID));
var thumbWidth = 42;
var thumbHeight = 42;
var thumbPhotoSize;
@ -421,10 +422,14 @@ angular.module('myApp.directives', ['myApp.filters'])
var peerID = AppMessagesManager.getMessagePeer(message);
var peerString = AppPeersManager.getPeerString(peerID);
$rootScope.$broadcast('history_focus', {peerString: peerString, messageID: message.id});
$rootScope.$broadcast('history_focus', {peerString: peerString, messageID: message.mid});
})
}
onContentLoaded(function () {
$scope.$emit('ui_height');
})
}
})
@ -465,7 +470,7 @@ angular.module('myApp.directives', ['myApp.filters'])
function link ($scope, element, attrs) {
var message = $scope.message;
var msgID = message.id;
var msgID = message.mid;
// var msgID = $scope.$eval(attrs.myMessageText);
// var message = AppMessagesManager.getMessage(msgID);
@ -473,7 +478,7 @@ angular.module('myApp.directives', ['myApp.filters'])
if (message.pending) {
var unlink = $scope.$on('messages_pending', function () {
if (message.id != msgID) {
if (message.mid != msgID) {
updateHtml(message, element);
unlink();
}
@ -2546,6 +2551,9 @@ angular.module('myApp.directives', ['myApp.filters'])
return;
}
AppChatsManager.getChatFull(chatID).then(function (chatFull) {
if (chatFull.participants_count) {
participantsCount = chatFull.participants_count;
}
var participantsVector = (chatFull.participants || {}).participants || [];
participantsCount = participantsVector.length;
angular.forEach(participantsVector, function (participant) {
@ -2920,7 +2928,7 @@ angular.module('myApp.directives', ['myApp.filters'])
if ($scope.message &&
!$scope.message.out &&
$scope.message.media_unread) {
AppMessagesManager.readMessages([$scope.message.id]);
AppMessagesManager.readMessages([$scope.message.mid]);
}
}, 300);
});

View File

@ -27,6 +27,14 @@
"group_modal_members": "Members",
"group_modal_members_kick": "Remove",
"channel_modal_info": "Channel info",
"channel_modal_share_link": "Share link",
"channel_modal_share_loading": "Loading{dots}",
"channel_modal_join": "Join channel",
"channel_modal_add_member": "Invite members",
"channel_modal_leave_channel": "Leave channel",
"channel_modal_delete_channel": "Delete channel",
"country_select_modal_title": "Country",
"settings_modal_title": "Settings",
@ -173,6 +181,12 @@
"group_edit_submit": "Save",
"group_edit_submit_active": "Saving...",
"channel_edit_modal_title": "Edit channel",
"channel_edit_name": "Channel name",
"channel_edit_about": "Channel description",
"channel_edit_submit": "Save",
"channel_edit_submit_active": "Saving...",
"group_invite_link_modal_title": "Invite link",
"group_invite_link_link_label": "Copy link",
"group_invite_link_loading": "Loading...",
@ -204,6 +218,9 @@
"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_revoke_channel_link": "Are you sure you want to revoke this link? Once you do, no one will be able to join the channel using it.",
"confirm_modal_delete_channel_md": "Are you sure you want to delete this channel?\n\nAll messages will be removed and all messages will be lost.",
"confirm_modal_are_u_sure": "Are you sure?",
"confirm_modal_logout_submit": "Log out",

View File

@ -113,8 +113,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
usernames[searchUsername] = userID;
}
apiUser.sortName = SearchIndexManager.cleanSearchText(apiUser.first_name + ' ' + (apiUser.last_name || ''));
apiUser.pFlags = {
self: (apiUser.flags & (1 << 10)) > 0,
contact: (apiUser.flags & (1 << 11)) > 0,
@ -125,6 +123,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
botNoGroups: (apiUser.flags & (1 << 16)) > 0
};
apiUser.sortName = apiUser.pFlags.deleted ? '' : SearchIndexManager.cleanSearchText(apiUser.first_name + ' ' + (apiUser.last_name || ''));
var nameWords = apiUser.sortName.split(' ');
var firstWord = nameWords.shift();
var lastWord = nameWords.pop();
@ -553,6 +553,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
usernames = {},
chatsFull = {},
chatFullPromises = {},
channelAccess = {},
cachedPhotoLocations = {};
function saveApiChats (apiChats) {
@ -565,6 +566,23 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
apiChat.rTitle = RichTextProcessor.wrapRichText(apiChat.title, {noLinks: true, noLinebreaks: true}) || _('chat_title_deleted');
var flags = apiChat.flags;
apiChat.pFlags = {
creator: (flags & (1 << 0)) > 0,
kicked: (flags & (1 << 1)) > 0,
left: (flags & (1 << 2)) > 0
};
if (apiChat._ == 'channel') {
angular.extend(apiChat.pFlags, {
editor: (apiChat.flags & (1 << 3)) > 0,
moderator: (apiChat.flags & (1 << 4)) > 0,
broadcast: (apiChat.flags & (1 << 5)) > 0,
username: (apiChat.flags & (1 << 6)) > 0,
verified: (apiChat.flags & (1 << 7)) > 0
});
};
var titleWords = SearchIndexManager.cleanSearchText(apiChat.title || '').split(' ');
var firstWord = titleWords.shift();
var lastWord = titleWords.pop();
@ -597,8 +615,17 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return usernames[username] || 0;
}
function saveChannelAccess (id, accessHash) {
channelAccess[id] = accessHash;
}
function isChannel (id) {
return (chats[id] || {})._ == 'channel';
var chat = chats[id];
if (chat && chat._ == 'channel' ||
channelAccess[id]) {
return true;
}
return false;
}
function getChatInput (id) {
@ -612,11 +639,14 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return {
_: 'inputChannel',
channel_id: id,
access_hash: getChat(id).access_hash || 0
access_hash: getChat(id).access_hash || channelAccess[id] || 0
}
}
function getChatFull(id) {
if (isChannel(id)) {
return getChannelFull(id);
}
if (chatsFull[id] !== undefined) {
if (chats[id].version == chatsFull[id].participants.version ||
chats[id].left) {
@ -631,13 +661,72 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}).then(function (result) {
saveApiChats(result.chats);
AppUsersManager.saveApiUsers(result.users);
if (result.full_chat && result.full_chat.chat_photo.id) {
AppPhotosManager.savePhoto(result.full_chat.chat_photo);
var fullChat = result.full_chat;
if (fullChat && fullChat.chat_photo.id) {
AppPhotosManager.savePhoto(fullChat.chat_photo);
}
delete chatFullPromises[id];
chatsFull[id] = fullChat;
$rootScope.$broadcast('chat_full_update', id);
return chatsFull[id] = result.full_chat;
return fullChat;
});
}
function getChannelFull (id, force) {
if (chatsFull[id] !== undefined && !force) {
return $q.when(chatsFull[id]);
}
if (chatFullPromises[id] !== undefined) {
return chatFullPromises[id];
}
return chatFullPromises[id] = MtpApiManager.invokeApi('channels.getFullChannel', {
channel: getChannelInput(id)
}).then(function (result) {
saveApiChats(result.chats);
AppUsersManager.saveApiUsers(result.users);
var fullChannel = result.full_chat;
var chat = getChat(id);
if (fullChannel && fullChannel.chat_photo.id) {
AppPhotosManager.savePhoto(fullChannel.chat_photo);
}
var participantsPromise;
if ((fullChannel.flags & 8) ||
chat.pFlags.creator ||
chat.pFlags.editor ||
chat.pFlags.moderator) {
participantsPromise = getChannelParticipants(id).then(function (participants) {
delete chatFullPromises[id];
fullChannel.participants = {
_: 'channelParticipants',
participants: participants
};
}, function (error) {
error.handled = true;
});
} else {
participantsPromise = $q.when();
}
return participantsPromise.then(function () {
delete chatFullPromises[id];
chatsFull[id] = fullChannel;
$rootScope.$broadcast('chat_full_update', id);
return fullChannel;
});
});
}
function getChannelParticipants (id) {
return MtpApiManager.invokeApi('channels.getParticipants', {
channel: getChannelInput(id),
filter: {_: 'channelParticipantsRecent'},
offset: 0,
limit: 200
}).then(function (result) {
AppUsersManager.saveApiUsers(result.users);
return result.participants;
});
}
@ -688,25 +777,33 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var chatFull = angular.copy(fullChat),
chat = getChat(id);
if (chatFull.participants && chatFull.participants._ == 'chatParticipants') {
MtpApiManager.getUserID().then(function (myID) {
chatFull.isAdmin = (myID == chatFull.participants.admin_id);
angular.forEach(chatFull.participants.participants, function(participant){
participant.user = AppUsersManager.getUser(participant.user_id);
participant.canLeave = myID == participant.user_id;
participant.canKick = !participant.canLeave && (chatFull.isAdmin || myID == participant.inviter_id);
// just for order by last seen
participant.user = AppUsersManager.getUser(participant.user_id);
});
});
}
if (chatFull.participants && chatFull.participants._ == 'channelParticipants') {
var isAdmin = chat.pFlags.creator || chat.pFlags.editor || chat.pFlags.moderator;
angular.forEach(chatFull.participants.participants, function(participant) {
participant.canLeave = !chat.pFlags.creator && participant._ == 'channelParticipantSelf';
participant.canKick = isAdmin && participant._ == 'channelParticipant';
// just for order by last seen
participant.user = AppUsersManager.getUser(participant.user_id);
});
}
if (chatFull.about) {
chatFull.rAbout = RichTextProcessor.wrapRichText(chatFull.about, {noLinebreaks: true});
}
chatFull.thumb = {
placeholder: 'img/placeholders/GroupAvatar'+(Config.Mobile ? chat.num : Math.ceil(chat.num / 2))+'@2x.png',
location: chat && chat.photo && chat.photo.photo_small,
width: 72,
height: 72,
size: 0
};
chatFull.peerString = getChatString(id);
chatFull.chat = chat;
@ -717,12 +814,21 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var scope = $rootScope.$new();
scope.chatID = chatID;
var modalInstance = $modal.open({
templateUrl: templateUrl('chat_modal'),
controller: 'ChatModalController',
scope: scope,
windowClass: 'chat_modal_window mobile_modal'
});
if (isChannel(chatID)) {
var modalInstance = $modal.open({
templateUrl: templateUrl('channel_modal'),
controller: 'ChannelModalController',
scope: scope,
windowClass: 'chat_modal_window channel_modal_window mobile_modal'
});
} else {
var modalInstance = $modal.open({
templateUrl: templateUrl('chat_modal'),
controller: 'ChatModalController',
scope: scope,
windowClass: 'chat_modal_window mobile_modal'
});
}
}
$rootScope.$on('apiUpdate', function (e, update) {
@ -779,9 +885,11 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
saveApiChat: saveApiChat,
getChat: getChat,
isChannel: isChannel,
saveChannelAccess: saveChannelAccess,
getChatInput: getChatInput,
getChannelInput: getChannelInput,
getChatFull: getChatFull,
getChannelFull: getChannelFull,
getChatPhoto: getChatPhoto,
getChatString: getChatString,
getChatInviteLink: getChatInviteLink,
@ -806,6 +914,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
};
}
else if (firstChar == 'c') {
AppChatsManager.saveChannelAccess(peerParams[0], peerParams[1]);
return {
_: 'inputPeerChannel',
channel_id: peerParams[0],
@ -875,13 +984,13 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function resolveUsername (username) {
var searchUserName = SearchIndexManager.cleanUsername(username);
var foundUserID, foundChatID, foundPeerID, foundUsername;
if (foundUserID == AppUsersManager.resolveUsername(searchUserName)) {
if (foundUserID = AppUsersManager.resolveUsername(searchUserName)) {
foundUsername = AppUsersManager.getUser(foundUserID).username;
if (SearchIndexManager.cleanUsername(foundUsername) == searchUserName) {
return qSync.when(foundUserID);
}
}
if (foundChatID == AppChatsManager.resolveUsername(searchUserName)) {
if (foundChatID = AppChatsManager.resolveUsername(searchUserName)) {
foundUsername = AppChatsManager.getChat(foundChatID).username;
if (SearchIndexManager.cleanUsername(foundUsername) == searchUserName) {
return qSync.when(-foundChatID);
@ -1171,8 +1280,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var peerText = AppPeersManager.getPeerSearchText(peerID);
SearchIndexManager.indexObject(peerID, peerText, dialogsIndex);
var messageID = dialog.top_important_message;
dialog.top_message = peerID + '_' + messageID;
var mid = getFullMessageID(dialog.top_important_message, -peerID);
dialog.top_message = mid;
var message = getMessage(dialog.top_message);
var topDate = message.date;
@ -1187,7 +1296,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
pushDialogToStorage(dialog);
if (historiesStorage[peerID] === undefined) {
var historyStorage = {count: null, history: [messageID], pending: []};
var historyStorage = {count: null, history: [mid], pending: []};
historiesStorage[peerID] = historyStorage;
}
@ -1305,15 +1414,15 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var promise;
if (AppPeersManager.isChannel(peerID)) {
promise = MtpApiManager.invokeApi('channels.getImportantHistory', {
peer: inputPeer,
offset_id: maxID || 0,
channel: AppChatsManager.getChannelInput(-peerID),
offset_id: maxID ? getMessageLocalID(maxID) : 0,
add_offset: offset || 0,
limit: limit || 0
}, {noErrorBox: true});
} else {
promise = MtpApiManager.invokeApi('messages.getHistory', {
peer: inputPeer,
offset_id: maxID || 0,
offset_id: maxID ? getMessageLocalID(maxID) : 0,
add_offset: offset || 0,
limit: limit || 0
}, {noErrorBox: true});
@ -1359,6 +1468,40 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
});
}
var channelLocals = {};
var channelsByLocals = {};
var channelCurLocal = 0;
var fullMsgIDModulus = 4294967296;
function getFullMessageID (msgID, channelID) {
if (!channelID) {
return msgID;
}
msgID = getMessageLocalID(msgID);
var localStart = channelLocals[channelID];
if (!localStart) {
localStart = (++channelCurLocal) * fullMsgIDModulus;
channelsByLocals[localStart] = channelID;
channelLocals[channelID] = localStart;
}
return localStart + msgID;
}
function getMessageIDInfo (fullMsgID) {
if (fullMsgID < fullMsgIDModulus) {
return [fullMsgID, 0];
}
var msgID = fullMsgID % fullMsgIDModulus;
var channelID = channelsByLocals[fullMsgID - msgID];
return [msgID, channelID];
}
function getMessageLocalID (fullMsgID) {
return fullMsgID % fullMsgIDModulus;
}
function fillHistoryStorage (inputPeer, maxID, fullLimit, historyStorage) {
// console.log('fill history storage', inputPeer, maxID, fullLimit, angular.copy(historyStorage));
return requestHistory (inputPeer, maxID, fullLimit).then(function (historyResult) {
@ -1366,7 +1509,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var offset = 0;
if (!maxID && historyResult.messages.length) {
maxID = historyResult.messages[0].id + 1;
maxID = historyResult.messages[0].mid + 1;
}
if (maxID > 0) {
for (offset = 0; offset < historyStorage.history.length; offset++) {
@ -1381,7 +1524,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
if (mergeReplyKeyboard(historyStorage, message)) {
$rootScope.$broadcast('history_reply_markup', {peerID: AppPeersManager.getPeerID(inputPeer)});
}
historyStorage.history.push(message.id);
historyStorage.history.push(message.mid);
});
fullLimit -= historyResult.messages.length;
@ -1479,7 +1622,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var history = [];
angular.forEach(historyResult.messages, function (message) {
history.push(message.id);
history.push(message.mid);
});
if (!maxID && historyStorage.pending.length) {
history = historyStorage.pending.slice().concat(history);
@ -1523,7 +1666,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
function mergeReplyKeyboard (historyStorage, message) {
// console.log('merge', message.id, message.reply_markup, historyStorage.reply_markup);
// console.log('merge', message.mid, message.reply_markup, historyStorage.reply_markup);
if (!message.reply_markup &&
!message.out &&
!message.action) {
@ -1532,7 +1675,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var messageReplyMarkup = message.reply_markup;
var lastReplyMarkup = historyStorage.reply_markup;
if (messageReplyMarkup) {
if (lastReplyMarkup && lastReplyMarkup.id >= message.id) {
if (lastReplyMarkup && lastReplyMarkup.mid >= message.mid) {
return false;
}
if (messageReplyMarkup.pFlags.selective &&
@ -1540,12 +1683,12 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return false;
}
if (historyStorage.maxOutID &&
message.id < historyStorage.maxOutID &&
message.mid < historyStorage.maxOutID &&
messageReplyMarkup.pFlags.one_time) {
messageReplyMarkup.pFlags.hidden = true;
}
messageReplyMarkup = angular.extend({
id: message.id
id: message.mid
}, messageReplyMarkup);
if (messageReplyMarkup._ != 'replyKeyboardHide') {
messageReplyMarkup.fromID = message.from_id;
@ -1559,15 +1702,15 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
if (lastReplyMarkup) {
if (lastReplyMarkup.pFlags.one_time &&
!lastReplyMarkup.pFlags.hidden &&
(message.id > lastReplyMarkup.id || message.id < 0) &&
(message.mid > lastReplyMarkup.mid || message.mid < 0) &&
message.message) {
lastReplyMarkup.pFlags.hidden = true;
// console.log('set', historyStorage.reply_markup);
return true;
}
} else if (!historyStorage.maxOutID ||
message.id > historyStorage.maxOutID) {
historyStorage.maxOutID = message.id;
message.mid > historyStorage.maxOutID) {
historyStorage.maxOutID = message.mid;
}
}
@ -1580,7 +1723,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
) {
historyStorage.reply_markup = {
_: 'replyKeyboardHide',
id: message.id,
mid: message.mid,
flags: 0,
pFlags: {}
};
@ -1636,7 +1779,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
for (i = 0; i < historyStorage.history.length; i++) {
message = messagesStorage[historyStorage.history[i]];
if (message.media && neededContents[message.media._]) {
foundMsgs.push(message.id);
foundMsgs.push(message.mid);
if (foundMsgs.length >= neededLimit) {
break;
}
@ -1688,7 +1831,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
foundMsgs = [];
angular.forEach(searchResult.messages, function (message) {
foundMsgs.push(message.id);
foundMsgs.push(message.mid);
});
if (useSearchCache) {
@ -1753,6 +1896,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function readHistory (inputPeer) {
// console.trace('start read');
var peerID = AppPeersManager.getPeerID(inputPeer),
isChannel = AppPeersManager.isChannel(peerID),
historyStorage = historiesStorage[peerID],
foundDialog = getDialogByPeerID(peerID);
@ -1783,13 +1927,23 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return historyStorage.readPromise;
}
historyStorage.readPromise = MtpApiManager.invokeApi('messages.readHistory', {
peer: inputPeer,
offset: 0,
max_id: 0
}).then(function (affectedHistory) {
return processAffectedHistory(inputPeer, affectedHistory, 'messages.readHistory');
}).then(function () {
var apiPromise;
if (isChannel) {
apiPromise = MtpApiManager.invokeApi('channels.readHistory', {
channel: AppChatsManager.getChannelInput(-peerID),
max_id: 0
});
} else {
apiPromise = MtpApiManager.invokeApi('messages.readHistory', {
peer: inputPeer,
offset: 0,
max_id: 0
}).then(function (affectedHistory) {
return processAffectedHistory(inputPeer, affectedHistory, 'messages.readHistory');
});
}
historyStorage.readPromise = apiPromise.then(function () {
if (foundDialog[0]) {
// console.log('done read history', peerID);
foundDialog[0].unread_count = 0;
@ -1861,17 +2015,25 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function saveMessages (apiMessages) {
angular.forEach(apiMessages, function (apiMessage) {
if (apiMessage._ == 'messageEmpty') {
return;
}
apiMessage.unread = apiMessage.flags & 1 ? true : false;
apiMessage.out = apiMessage.flags & 2 ? true : false;
apiMessage.media_unread = apiMessage.flags & 32 ? true : false;
var toPeerID = AppPeersManager.getPeerID(apiMessage.to_id);
var isChannel = apiMessage.to_id._ == 'peerChannel';
var mid = isChannel ? toPeerID + '_' + apiMessage.id : apiMessage.id;
apiMessage.mid = mid;
var channelID = isChannel ? -toPeerID : 0;
var mid = getFullMessageID(apiMessage.id, channelID);
apiMessage.mid = mid;
messagesStorage[mid] = apiMessage;
if (apiMessage.reply_to_msg_id) {
apiMessage.reply_to_mid = getFullMessageID(apiMessage.reply_to_msg_id, channelID);
}
apiMessage.date -= serverTimeOffset;
apiMessage.toID = toPeerID;
apiMessage.fromID = apiMessage.from_id || toPeerID;
@ -1902,7 +2064,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
AppAudioManager.saveAudio(apiMessage.media.audio);
break;
case 'messageMediaWebPage':
AppWebPagesManager.saveWebPage(apiMessage.media.webpage, apiMessage.id, mediaContext);
AppWebPagesManager.saveWebPage(apiMessage.media.webpage, apiMessage.mid, mediaContext);
break;
}
}
@ -1913,8 +2075,13 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
apiMessage.action._ = 'messageActionChannelEditPhoto';
}
}
if (apiMessage.action._ == 'messageActionChatEditTitle' && isChannel) {
apiMessage.action._ = 'messageActionChannelEditTitle';
else if (isChannel) {
if (apiMessage.action._ == 'messageActionChatEditTitle') {
apiMessage.action._ = 'messageActionChannelEditTitle';
}
if (apiMessage.action._ == 'messageActionChatDeletePhoto') {
apiMessage.action._ = 'messageActionChannelDeletePhoto';
}
}
}
if (apiMessage.reply_markup) {
@ -2013,7 +2180,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
peer: inputPeer,
message: text,
random_id: randomID,
reply_to_msg_id: replyToMsgID,
reply_to_msg_id: getMessageLocalID(replyToMsgID),
entities: entities
}, sentRequestOptions).then(function (updates) {
if (updates._ == 'updateShortSentMessage') {
@ -2187,7 +2354,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
peer: inputPeer,
media: inputMedia,
random_id: randomID,
reply_to_msg_id: replyToMsgID
reply_to_msg_id: getMessageLocalID(replyToMsgID)
}).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
}, function (error) {
@ -2319,7 +2486,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
peer: inputPeer,
media: inputMedia,
random_id: randomID,
reply_to_msg_id: replyToMsgID
reply_to_msg_id: getMessageLocalID(replyToMsgID)
}).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
}, function (error) {
@ -2337,20 +2504,26 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
pendingByRandomID[randomIDS] = [peerID, messageID];
}
function forwardMessages (peerID, msgIDs) {
msgIDs = msgIDs.sort();
function forwardMessages (peerID, mids) {
mids = mids.sort();
var flags = 0;
var msgIDs = [];
var randomIDs = [];
var i;
var len = msgIDs.length;
for (var i = 0; i < msgIDs.length; i++) {
var len = mids.length;
var i, mid, msgID;
var fromChannel = getMessageIDInfo(mids[0])[1];
for (i = 0; i < len; i++) {
msgIDs.push(getMessageLocalID(mids[i]));
randomIDs.push([nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)]);
}
return MtpApiManager.invokeApi('messages.forwardMessages', {
peer: AppPeersManager.getInputPeerByID(peerID),
flags: flags,
from_peer: AppPeersManager.getInputPeerByID(-fromChannel),
id: msgIDs,
random_id: randomIDs
random_id: randomIDs,
to_peer: AppPeersManager.getInputPeerByID(peerID),
}).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
});
@ -2446,7 +2619,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
if (historyMessage = messagesForHistory[tempID]) {
messagesForHistory[finalMessage.id] = angular.extend(historyMessage, wrapForHistory(finalMessage.id));
messagesForHistory[finalMessage.mid] = angular.extend(historyMessage, wrapForHistory(finalMessage.mid));
delete historyMessage.pending;
delete historyMessage.error;
delete historyMessage.random_id;
@ -2654,12 +2827,12 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
}
var replyToMsgID = message.reply_to_msg_id;
var replyToMsgID = message.reply_to_mid;
if (replyToMsgID) {
if (messagesStorage[replyToMsgID] && false) {
if (messagesStorage[replyToMsgID]) {
message.reply_to_msg = wrapForDialog(replyToMsgID);
} else {
message.reply_to_msg = {id: replyToMsgID, loading: true};
message.reply_to_msg = {mid: replyToMsgID, loading: true};
if (needSingleMessages.indexOf(replyToMsgID) == -1) {
needSingleMessages.push(replyToMsgID);
if (fetchSingleMessagesTimeout === false) {
@ -2705,16 +2878,43 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
if (!needSingleMessages.length) {
return;
}
var msgIDs = needSingleMessages.slice();
var mids = needSingleMessages.slice();
needSingleMessages = [];
MtpApiManager.invokeApi('messages.getMessages', {
id: msgIDs
}).then(function (getMessagesResult) {
AppUsersManager.saveApiUsers(getMessagesResult.users);
AppChatsManager.saveApiChats(getMessagesResult.chats);
saveMessages(getMessagesResult.messages);
$rootScope.$broadcast('messages_downloaded', msgIDs);
var msgIDsByChannels = {};
var midsByChannels = {};
var i, mid, msgChannel, channelID;
for (i = 0; i < mids.length; i++) {
mid = mids[i];
msgChannel = getMessageIDInfo(mid);
channelID = msgChannel[1];
if (msgIDsByChannels[channelID] === undefined) {
msgIDsByChannels[channelID] = [];
midsByChannels[channelID] = [];
}
msgIDsByChannels[channelID].push(msgChannel[0]);
midsByChannels[channelID].push(mid);
}
angular.forEach(msgIDsByChannels, function (msgIDs, channelID) {
var promise;
if (channelID > 0) {
promise = MtpApiManager.invokeApi('channels.getMessages', {
channel: AppChatsManager.getChannelInput(channelID),
id: msgIDs
});
} else {
promise = MtpApiManager.invokeApi('messages.getMessages', {
id: msgIDs
});
}
promise.then(function (getMessagesResult) {
AppUsersManager.saveApiUsers(getMessagesResult.users);
AppChatsManager.saveApiChats(getMessagesResult.chats);
saveMessages(getMessagesResult.messages);
$rootScope.$broadcast('messages_downloaded', midsByChannels[channelID]);
})
})
}
@ -2757,20 +2957,20 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
if (curMessage.fwdFromID &&
curMessage.media &&
curMessage.media.document &&
curMessage.media.document.sticker &&
(curMessage.from_id != (prevMessage || {}).from_id || !(prevMessage || {}).fwdFromID)) {
(curMessage.media.document.sticker || curMessage.media.document.audioTitle) &&
(curMessage.fromID != (prevMessage || {}).fromID || !(prevMessage || {}).fwdFromID)) {
delete curMessage.fwdFromID;
curMessage._ = 'message';
}
if (prevMessage &&
curMessage.from_id == prevMessage.from_id &&
curMessage.fromID == prevMessage.fromID &&
!prevMessage.fwdFromID == !curMessage.fwdFromID &&
!prevMessage.action &&
!curMessage.action &&
curMessage.date < prevMessage.date + 900) {
var singleLine = curMessage.message && curMessage.message.length < 70 && curMessage.message.indexOf("\n") == -1 && !curMessage.reply_to_msg_id;
var singleLine = curMessage.message && curMessage.message.length < 70 && curMessage.message.indexOf("\n") == -1 && !curMessage.reply_to_mid;
if (groupFwd && curMessage.fwdFromID && curMessage.fwdFromID == prevMessage.fwdFromID) {
curMessage.grouped = singleLine ? 'im_grouped_fwd_short' : 'im_grouped_fwd';
} else {
@ -2922,13 +3122,13 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
notification.onclick = function () {
$rootScope.$broadcast('history_focus', {
peerString: peerString,
messageID: message.flags & 16 ? message.id : 0,
messageID: message.flags & 16 ? message.mid : 0,
});
};
notification.message = notificationMessage;
notification.image = notificationPhoto.placeholder;
notification.key = 'msg' + message.id;
notification.key = 'msg' + message.mid;
notification.tag = peerString;
if (notificationPhoto.location && !notificationPhoto.location.empty) {
@ -3025,14 +3225,16 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
peerID = getMessagePeer(message),
historyStorage = historiesStorage[peerID];
saveMessages([message]);
if (historyStorage !== undefined) {
var history = historyStorage.history;
if (history.indexOf(message.id) != -1) {
if (history.indexOf(message.mid) != -1) {
return false;
}
var topMsgID = history[0];
history.unshift(message.id);
if (message.id > 0 && message.id < topMsgID) {
history.unshift(message.mid);
if (message.mid > 0 && message.mid < topMsgID) {
history.sort(function (a, b) {
return b - a;
});
@ -3043,12 +3245,11 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} else {
historyStorage = historiesStorage[peerID] = {
count: null,
history: [message.id],
history: [message.mid],
pending: []
};
}
saveMessages([message]);
if (mergeReplyKeyboard(historyStorage, message)) {
$rootScope.$broadcast('history_reply_markup', {peerID: peerID})
@ -3058,21 +3259,21 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
AppUsersManager.forceUserOnline(message.from_id);
}
var randomID = pendingByMessageID[message.id],
var randomID = pendingByMessageID[message.mid],
pendingMessage;
if (randomID) {
if (pendingMessage = finalizePendingMessage(randomID, message)) {
$rootScope.$broadcast('history_update', {peerID: peerID});
}
delete pendingByMessageID[message.id];
delete pendingByMessageID[message.mid];
}
if (!pendingMessage) {
if (newMessagesToHandle[peerID] === undefined) {
newMessagesToHandle[peerID] = [];
}
newMessagesToHandle[peerID].push(message.id);
newMessagesToHandle[peerID].push(message.mid);
if (!newMessagesHandlePromise) {
newMessagesHandlePromise = $timeout(handleNewMessages, 0);
}
@ -3088,7 +3289,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
dialogsStorage.dialogs.splice(foundDialog[1], 1);
dialogsStorage.dialogs.unshift(dialog);
}
dialog.top_message = message.id;
dialog.top_message = message.mid;
if (inboxUnread) {
dialog.unread_count++;
}
@ -3098,7 +3299,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
dialog = {
peerID: peerID,
unread_count: inboxUnread ? 1 : 0,
top_message: message.id
top_message: message.mid
};
dialogsStorage.dialogs.unshift(dialog);
}
@ -4586,7 +4787,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
message: updateMessage.message,
fwd_from_id: updateMessage.fwd_from_id,
fwd_date: updateMessage.fwd_date,
reply_to_msg_id: updateMessage.reply_to_msg_id,
reply_to_msg_id: updateMessage.reply_to_msg_id
},
pts: updateMessage.pts,
pts_count: updateMessage.pts_count

View File

@ -3652,7 +3652,7 @@ a.countries_modal_search_clear {
height: 18px;
margin: 17px 0 0 16px;
.image-2x('../img/icons/ProfileIcons.png', 40px, 360px);
.image-2x('../img/icons/ProfileIcons.png', 40px, 420px);
background-position: -10px -164px;
}
@ -3667,7 +3667,7 @@ a.countries_modal_search_clear {
height: 22px;
margin: 17px 0 0 13px;
.image-2x('../img/icons/ProfileIcons.png', 40px, 360px);
.image-2x('../img/icons/ProfileIcons.png', 40px, 420px);
background-position: -7px -280px;
}
@ -3682,7 +3682,7 @@ a.countries_modal_search_clear {
height: 20px;
margin: 18px 0 0 16px;
.image-2x('../img/icons/ProfileIcons.png', 40px, 360px);
.image-2x('../img/icons/ProfileIcons.png', 40px, 420px);
background-position: -10px -220px;
}
@ -3728,7 +3728,7 @@ a.countries_modal_search_clear {
margin-top: 5px;
position: absolute;
.image-2x('../img/icons/ProfileIcons.png', 40px, 360px);
.image-2x('../img/icons/ProfileIcons.png', 40px, 420px);
background-position: 0 0;
.md_modal_iconed_section_toggle & {
@ -3748,6 +3748,13 @@ a.countries_modal_search_clear {
margin-top: 3px;
}
&_about {
width: 20px;
height: 20px;
background-position: -10px -344px;
margin-top: 0px;
}
&_notification {
width: 17px;
height: 20px;

View File

@ -0,0 +1,28 @@
<div class="md_simple_modal_wrap" my-modal-position>
<div class="md_simple_modal_body">
<form class="modal_simple_form" ng-submit="updateChannel()">
<h4 my-i18n="channel_edit_modal_title"></h4>
<div class="md-input-group" my-labeled-input>
<label class="md-input-label" my-i18n="channel_edit_name"></label>
<input class="md-input" my-focused type="text" ng-model="channel.title" />
</div>
<div class="md-input-group" my-labeled-input>
<label class="md-input-label" my-i18n="channel_edit_about"></label>
<input class="md-input" type="text" ng-model="channel.about" />
</div>
</form>
</div>
<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: channel.updating}" ng-click="updateChannel()" ng-bind="channel.updating ? 'channel_edit_submit_active' : 'channel_edit_submit' | i18n" ng-disabled="channel.updating"></button>
</div>
</div>

View File

@ -0,0 +1,136 @@
<div class="chat_modal_wrap md_modal_wrap" my-modal-position>
<div class="md_modal_head">
<div class="md_modal_title_wrap">
<div class="md_modal_actions_wrap clearfix">
<a class="md_modal_action md_modal_action_close" ng-click="$close()" my-i18n="modal_close"></a>
<a class="md_modal_action" ng-if="chatFull.chat.pFlags.creator" ng-click="editChannel()" my-i18n="modal_edit"></a>
</div>
<div class="md_modal_title" my-i18n="channel_modal_info"></div>
</div>
<div class="peer_modal_profile_wrap clearfix">
<div class="peer_modal_photo_wrap pull-left" ng-switch="photo.updating">
<div ng-switch-when="true" class="peer_modal_photo md_photo_loading loading_dots">
<i></i><i></i><i></i>
</div>
<a ng-switch-default ng-click="openPhoto(chatFull.chat_photo.id, {p: -chatFull.chat.id})" class="peer_modal_photo" my-peer-photolink="::-chatFull.chat.id" img-class="peer_modal_photo" no-open="true" watch="true" ng-class="{disabled: !chatFull.chat.photo.photo_small}" ng-disabled="!chatFull.chat.photo.photo_small"></a>
</div>
<div class="peer_modal_profile">
<div class="peer_modal_profile_name" my-peer-link="-chatFull.chat.id"></div>
<div class="peer_modal_profile_description" ng-if="chatFull.participants_count > 0">
<ng-pluralize count="chatFull.participants_count"
when="group_modal_pluralize_participants">
</ng-pluralize>
</div>
</div>
</div>
</div>
<div class="md_modal_split_actions_wrap" ng-if="chatFull.chat.pFlags.creator">
<div class="md_modal_split_actions">
<div class="md_modal_split_action">
<input my-file-upload type="file" multiple="false" class="im_attach_input" size="120" multiple="false" accept="image/x-png, image/png, image/gif, image/jpeg" title="{{'group_modal_update_photo' | i18n}}" />
<i class="md_modal_split_action_camera"></i>
</div>
</div>
</div>
<div class="md_modal_body">
<div class="md_modal_sections">
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_number" ng-if="chatFull.rAbout || chatFull.chat.username || chatFull.chat.pFlags.creator">
<i class="md_modal_section_icon md_modal_section_icon_about"></i>
<div class="md_modal_section_param_wrap" ng-if="chatFull.about.length > 0">
<div class="md_modal_section_param_value">
<span ng-bind-html="chatFull.rAbout"></span>
</div>
<div class="md_modal_section_param_name" my-i18n="user_modal_about"></div>
</div>
<div class="md_modal_section_param_wrap" ng-if="chatFull.chat.username">
<div class="md_modal_section_param_value">
<a class="settings_modal_username_link" ng-click="shareLink($event)" ng-bind="'https://telegram.me/' + chatFull.chat.username" ng-href="https://telegram.me/{{chatFull.chat.username}}" target="_blank"></a>
</div>
<div class="md_modal_section_param_name" my-i18n="channel_modal_share_link"></div>
</div>
<div class="md_modal_section_param_wrap" ng-if="!chatFull.chat.username &amp;&amp; chatFull.chat.pFlags.creator">
<div class="md_modal_section_param_value" ng-switch="chatFull.exported_invite._">
<a ng-switch-when="chatInviteExported" class="settings_modal_username_link" ng-click="shareLink($event)" ng-bind="chatFull.exported_invite.link" ng-href="{{chatFull.exported_invite.link}}" target="_blank"></a>
<span ng-switch-default my-i18n="channel_modal_share_loading">
<my-i18n-param name="dots"><span my-loading-dots></span></my-i18n-param>
</span>
</div>
<div class="md_modal_section_param_name" my-i18n="channel_modal_share_link"></div>
</div>
</div>
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_link" ng-if="chatFull.chat.pFlags.creator || chatFull.chat.pFlags.left">
<i class="md_modal_section_icon md_modal_section_icon_person"></i>
<div class="md_modal_section_link_wrap" ng-switch="chatFull.chat.pFlags.left">
<a ng-switch-when="true" class="md_modal_section_link" ng-click="joinChannel()" my-i18n="channel_modal_join"></a>
<a ng-switch-default class="md_modal_section_link" ng-click="inviteToChannel()" my-i18n="channel_modal_add_member"></a>
</div>
</div>
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_toggle">
<i class="md_modal_section_icon md_modal_section_icon_notification"></i>
<a class="md_modal_section_toggle_wrap tg_checkbox" ng-click="settings.notifications = !settings.notifications" ng-class="settings.notifications ? 'tg_checkbox_on' : ''">
<span class="icon icon-checkbox-outer"><i class="icon-checkbox-inner"></i></span>
<span class="tg_checkbox_label" my-i18n="group_modal_notifications"></span>
</a>
</div>
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_link" ng-if="chatFull.chat.pFlags.creator || !chatFull.chat.pFlags.left && !chatFull.chat.pFlags.kicked">
<i class="md_modal_section_icon md_modal_section_icon_more"></i>
<div class="md_modal_section_link_wrap" ng-if="!chatFull.chat.pFlags.creator && !chatFull.chat.pFlags.left && !chatFull.chat.pFlags.kicked">
<a class="md_modal_section_link" ng-click="leaveChannel()" my-i18n="channel_modal_leave_channel"></a>
</div>
<div class="md_modal_section_link_wrap" ng-if="chatFull.chat.pFlags.creator">
<a class="md_modal_section_link md_modal_section_link_danger" ng-click="deleteChannel()" my-i18n="channel_modal_delete_channel"></a>
</div>
</div>
</div>
<div ng-if="chatFull.participants.participants.length > 0">
<div class="md_modal_section_splitter"></div>
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_peers">
<i class="md_modal_section_icon md_modal_section_icon_people"></i>
<div class="md_modal_section_peers_wrap">
<div class="md_modal_list_peer_wrap clearfix" ng-repeat="participant in chatFull.participants.participants | orderBy:'-user.sortStatus'">
<a ng-if="participant.canLeave" ng-click="leaveChannel()" class="md_modal_list_peer_action pull-right" my-i18n="group_modal_menu_leave"></a>
<a ng-if="participant.canKick" ng-click="kickFromChannel(participant.user_id)" class="md_modal_list_peer_action pull-right" my-i18n="group_modal_members_kick"></a>
<a class="md_modal_list_peer_photo pull-left" my-peer-photolink="::participant.user_id" img-class="md_modal_list_peer_photo"></a>
<div class="md_modal_list_peer_name">
<a class="md_modal_list_peer_name" my-peer-link="participant.user_id"></a>
</div>
<div class="md_modal_list_peer_description" my-user-status="::participant.user_id" bot-chat-privacy="true"></div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -6,18 +6,32 @@
<h4 my-i18n="group_invite_link_modal_title"></h4>
<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="'ui_invite_select'"></textarea>
<div ng-switch="exportedInvite.canRevoke">
<div ng-switch-when="true">
<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="'ui_invite_select'"></textarea>
</div>
</div>
<div ng-switch-default>
<div class="md-input-group" my-labeled-input>
<label class="md-input-label" my-i18n="group_invite_link_link_label"></label>
<input class="md-input" type="text" ng-model="exportedInvite.link" my-copy-field="'ui_invite_select'" />
</div>
</div>
</div>
</div>
</div>
<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="revokeLink()" ng-bind="exportedInvite.revoking ? 'group_invite_revoke_active' : 'group_invite_revoke' | i18n" ng-disabled="exportedInvite.revoking"></button>
<div class="md_simple_modal_footer" ng-switch="exportedInvite.canRevoke">
<div ng-switch-when="true">
<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="revokeLink()" ng-bind="exportedInvite.revoking ? 'group_invite_revoke_active' : 'group_invite_revoke' | i18n" ng-disabled="exportedInvite.revoking"></button>
</div>
</div>
</div>

View File

@ -49,6 +49,8 @@
<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>
<div ng-switch-when="REVOKE_CHANNEL_INVITE_LINK" my-i18n="confirm_modal_revoke_channel_link"></div>
<div ng-switch-when="CHANNEL_DELETE" my-i18n="confirm_modal_delete_channel_md"></div>
<span ng-switch-default ng-switch="message.length > 0">

View File

@ -1,4 +1,4 @@
<a class="im_dialog" ng-mousedown="dialogSelect(dialogMessage.peerString, dialogMessage.unreadCount == -1 && dialogMessage.id)">
<a class="im_dialog" ng-mousedown="dialogSelect(dialogMessage.peerString, dialogMessage.unreadCount == -1 && dialogMessage.mid)">
<div class="im_dialog_meta pull-right text-right">
<div class="im_dialog_date" ng-bind="dialogMessage.dateText"></div>

View File

@ -71,7 +71,7 @@
<div class="im_dialogs_messages_wrap" ng-show="foundMessages.length > 0">
<h5 my-i18n="im_messages"></h5>
<ul class="nav nav-pills nav-stacked">
<li class="im_dialog_wrap" my-dialog dialog-message="dialogMessage" ng-repeat="dialogMessage in foundMessages track by dialogMessage.id" ng-class="{active: curDialog.peerID == dialogMessage.peerID &amp;&amp; curDialog.messageID == dialogMessage.id}"></li>
<li class="im_dialog_wrap" my-dialog dialog-message="dialogMessage" ng-repeat="dialogMessage in foundMessages track by dialogMessage.mid" ng-class="{active: curDialog.peerID == dialogMessage.peerID &amp;&amp; curDialog.messageID == dialogMessage.id}"></li>
</ul>
</div>

View File

@ -1,4 +1,4 @@
<div class="im_message_outer_wrap" ng-click="toggleMessage(historyMessage.id, $event)">
<div class="im_message_outer_wrap" ng-click="toggleMessage(historyMessage.mid, $event)">
<div class="im_message_wrap clearfix" ng-switch="::historyMessage._ == 'messageService'">
@ -43,7 +43,7 @@
<a class="im_message_author" my-peer-link="historyMessage.fromID" short="historyMessage.toID > 0" color="historyMessage.toID < 0" no-watch="true"></a>
<a class="im_message_reply_wrap" my-reply-message="historyMessage.reply_to_msg" ng-if="::historyMessage.reply_to_msg_id"></a>
<a class="im_message_reply_wrap" my-reply-message="historyMessage.reply_to_msg" ng-if="::historyMessage.reply_to_mid"></a>
<div ng-if="::historyMessage.fwdFromID || false" class="im_message_fwd_from">
<a class="im_message_fwd_photo pull-left" my-peer-photolink="::historyMessage.fwdFromID" img-class="im_message_fwd_photo"></a>
@ -54,16 +54,16 @@
<div class="im_message_text" ng-if="::historyMessage.message.length || false" my-message-text="::historyMessage" dir="auto"></div>
<div ng-if="::historyMessage.media || historyMessage.id < 0 ? true : false" class="im_message_media" ng-switch="historyMessage.media._">
<div ng-if="::historyMessage.media || historyMessage.mid < 0 ? true : false" class="im_message_media" ng-switch="historyMessage.media._">
<div ng-switch-when="messageMediaPhoto" my-message-photo="historyMessage.media" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaVideo" my-message-video="historyMessage.media" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaDocument" my-message-document="historyMessage.media.document" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaPhoto" my-message-photo="historyMessage.media" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaVideo" my-message-video="historyMessage.media" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaDocument" my-message-document="historyMessage.media.document" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaAudio" class="im_message_audio" my-audio-player audio="historyMessage.media.audio" message="historyMessage"></div>
<div ng-switch-when="messageMediaGeo" my-message-geo="historyMessage.media"></div>
<div ng-switch-when="messageMediaVenue" my-message-venue="historyMessage.media"></div>
<div ng-switch-when="messageMediaContact" class="im_message_contact" my-message-contact></div>
<div ng-switch-when="messageMediaWebPage" class="im_message_webpage" my-message-webpage="historyMessage.media.webpage" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaWebPage" class="im_message_webpage" my-message-webpage="historyMessage.media.webpage" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaPending" my-message-pending></div>
<div ng-switch-when="messageMediaUnsupported">
<div class="im_message_text">

View File

@ -12,7 +12,7 @@
/>
</div>
<div class="im_message_reply_author" ng-switch-default>
<span my-peer-link="replyMessage.from_id"></span>
<span my-peer-link="replyMessage.fromID" peer-watch="true"></span>
</div>
<div class="im_message_reply_body" ng-switch-default>
<span class="im_reply_message_media" ng-if="replyMessage.media" ng-switch="replyMessage.media._">

View File

@ -1,4 +1,4 @@
<a class="im_dialog" ng-mousedown="dialogSelect(dialogMessage.peerString, dialogMessage.unreadCount == -1 && dialogMessage.id)">
<a class="im_dialog" ng-mousedown="dialogSelect(dialogMessage.peerString, dialogMessage.unreadCount == -1 && dialogMessage.mid)">
<div class="im_dialog_meta pull-right text-right">
<div class="im_dialog_date" ng-bind="dialogMessage.dateText"></div>

View File

@ -69,7 +69,7 @@
<div class="im_dialogs_messages_wrap" ng-show="foundMessages.length > 0">
<h5 my-i18n="im_messages"></h5>
<ul class="nav nav-pills nav-stacked">
<li class="im_dialog_wrap" my-dialog dialog-message="dialogMessage" ng-repeat="dialogMessage in foundMessages track by dialogMessage.id" ng-class="{active: curDialog.peerID == dialogMessage.peerID &amp;&amp; curDialog.messageID == dialogMessage.id}"></li>
<li class="im_dialog_wrap" my-dialog dialog-message="dialogMessage" ng-repeat="dialogMessage in foundMessages track by dialogMessage.mid" ng-class="{active: curDialog.peerID == dialogMessage.peerID &amp;&amp; curDialog.messageID == dialogMessage.mid}"></li>
</ul>
</div>

View File

@ -1,4 +1,4 @@
<div class="im_message_outer_wrap" ng-click="toggleMessage(historyMessage.id, $event)">
<div class="im_message_outer_wrap" ng-click="toggleMessage(historyMessage.mid, $event)">
<div class="im_message_wrap clearfix" ng-switch="::historyMessage._ == 'messageService'">
@ -30,14 +30,14 @@
<div class="im_message_meta">
<i class="icon-message-status-tick"></i>
<span class="im_message_date" ng-bind="::historyMessage.date | time"></span>
<span class="im_message_date" ng-bind="::mhistoryMessage.date | time"></span>
</div>
<div class="im_message_body" ng-class="::{im_message_body_media: !!historyMessage.media && !historyMessage.media.rCaption}">
<a class="im_message_author" my-peer-link="historyMessage.from_id" short="!historyMessage.to_id.chat_id" color="historyMessage.to_id.chat_id > 0" no-watch="true"></a>
<a class="im_message_reply_wrap" my-reply-message="historyMessage.reply_to_msg" ng-if="::historyMessage.reply_to_msg_id"></a>
<a class="im_message_reply_wrap" my-reply-message="historyMessage.reply_to_msg" ng-if="::historyMessage.reply_to_mid"></a>
<div ng-if="::historyMessage.fwd_from_id > 0 &amp;&amp; !historyMessage.media" class="im_message_fwd_header" my-i18n="message_forwarded_message_mobile">
<a my-i18n-param="from" class="im_message_fwd_author" my-peer-link="historyMessage.fwd_from_id" no-watch="true"></a>
@ -46,9 +46,9 @@
<div ng-if="::historyMessage.media || false" class="im_message_media" ng-switch="historyMessage.media._">
<div ng-switch-when="messageMediaPhoto" my-message-photo="historyMessage.media" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaVideo" my-message-video="historyMessage.media" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaDocument" my-message-document="historyMessage.media.document" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaPhoto" my-message-photo="historyMessage.media" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaVideo" my-message-video="historyMessage.media" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaDocument" my-message-document="historyMessage.media.document" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaAudio" class="im_message_audio" my-audio-player audio="historyMessage.media.audio" message="historyMessage"></div>
<div ng-switch-when="messageMediaGeo" my-message-geo="historyMessage.media"></div>
<div ng-switch-when="messageMediaVenue" my-message-geo="historyMessage.media"></div>