New forward messages

This commit is contained in:
Igor Zhukov 2015-10-22 14:34:42 +02:00
parent efae2ce626
commit 7d77145ebb
18 changed files with 695 additions and 567 deletions

View File

@ -413,7 +413,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.$on('$routeUpdate', updateCurDialog); $scope.$on('$routeUpdate', updateCurDialog);
var pendingParams = false; var pendingParams = false;
var pendingShare = false; var pendingAttachment = false;
$scope.$on('history_focus', function (e, peerData) { $scope.$on('history_focus', function (e, peerData) {
$modalStack.dismissAll(); $modalStack.dismissAll();
if (peerData.peerString == $scope.curDialog.peer && if (peerData.peerString == $scope.curDialog.peer &&
@ -424,7 +424,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
var peerID = AppPeersManager.getPeerID(peerData.peerString); var peerID = AppPeersManager.getPeerID(peerData.peerString);
var username = AppPeersManager.getPeer(peerID).username; var username = AppPeersManager.getPeer(peerID).username;
var peer = username ? '@' + username : peerData.peerString; var peer = username ? '@' + username : peerData.peerString;
if (peerData.messageID || peerData.startParam || peerData.shareUrl) { if (peerData.messageID || peerData.startParam) {
pendingParams = { pendingParams = {
messageID: peerData.messageID, messageID: peerData.messageID,
startParam: peerData.startParam startParam: peerData.startParam
@ -432,11 +432,8 @@ angular.module('myApp.controllers', ['myApp.i18n'])
} else { } else {
pendingParams = false; pendingParams = false;
} }
if (peerData.shareUrl) { if (peerData.attachment) {
pendingShare = { pendingAttachment = peerData.attachment;
url: peerData.shareUrl,
text: peerData.shareText
};
} }
if ($routeParams.p != peer) { if ($routeParams.p != peer) {
$location.url('/im?p=' + peer); $location.url('/im?p=' + peer);
@ -619,9 +616,9 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.curDialog = angular.extend({ $scope.curDialog = angular.extend({
peer: peerString peer: peerString
}, addParams); }, addParams);
if (pendingShare) { if (pendingAttachment) {
$scope.$broadcast('peer_share', pendingShare); $scope.$broadcast('peer_draft_attachment', pendingAttachment);
pendingShare = false; pendingAttachment = false;
} }
}); });
} }
@ -1072,6 +1069,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
documents: 'inputMessagesFilterDocument', documents: 'inputMessagesFilterDocument',
audio: 'inputMessagesFilterAudio' audio: 'inputMessagesFilterAudio'
}, },
unfocusMessagePromise,
jump = 0, jump = 0,
moreJump = 0, moreJump = 0,
moreActive = false, moreActive = false,
@ -1258,8 +1256,18 @@ angular.module('myApp.controllers', ['myApp.i18n'])
if (history && if (history &&
history.ids.indexOf($scope.curDialog.messageID) != -1) { history.ids.indexOf($scope.curDialog.messageID) != -1) {
$scope.historyUnread = {}; $scope.historyUnread = {};
$scope.$broadcast('messages_focus', $scope.curDialog.messageID); var focusedMsgID = $scope.curDialog.messageID || 0;
$scope.$broadcast('messages_focus', focusedMsgID);
$scope.$broadcast('ui_history_change_scroll', true); $scope.$broadcast('ui_history_change_scroll', true);
$timeout.cancel(unfocusMessagePromise);
if (focusedMsgID) {
unfocusMessagePromise = $timeout(function () {
if ($scope.curDialog.messageID == focusedMsgID) {
$scope.$broadcast('messages_focus', 0);
}
}, 2800);
}
} else { } else {
loadHistory(); loadHistory();
} }
@ -1447,11 +1455,21 @@ angular.module('myApp.controllers', ['myApp.i18n'])
delete $scope.historyUnreadAfter; delete $scope.historyUnreadAfter;
} }
$scope.$broadcast('messages_unread_after'); $scope.$broadcast('messages_unread_after');
var focusedMsgID = $scope.curDialog.messageID || 0;
onContentLoaded(function () { onContentLoaded(function () {
$scope.$broadcast('messages_focus', $scope.curDialog.messageID || 0); $scope.$broadcast('messages_focus', focusedMsgID);
}); });
$scope.$broadcast('ui_history_change'); $scope.$broadcast('ui_history_change');
$timeout.cancel(unfocusMessagePromise);
if (focusedMsgID) {
unfocusMessagePromise = $timeout(function () {
if ($scope.curDialog.messageID == focusedMsgID) {
$scope.$broadcast('messages_focus', 0);
}
}, 2800);
}
AppMessagesManager.readHistory($scope.curDialog.inputPeer); AppMessagesManager.readHistory($scope.curDialog.inputPeer);
updateBotActions(); updateBotActions();
@ -1538,7 +1556,8 @@ angular.module('myApp.controllers', ['myApp.i18n'])
if (Config.Mobile) { if (Config.Mobile) {
$modal.open({ $modal.open({
templateUrl: templateUrl('message_actions_modal'), templateUrl: templateUrl('message_actions_modal'),
windowClass: 'message_actions_modal_window' windowClass: 'message_actions_modal_window',
scope: $scope.$new()
}).result.then(function (action) { }).result.then(function (action) {
switch (action) { switch (action) {
case 'reply': case 'reply':
@ -1662,15 +1681,14 @@ angular.module('myApp.controllers', ['myApp.i18n'])
}); });
} }
if (selectedMessageIDs.length) { if (selectedMessageIDs.length) {
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) { PeersSelectService.selectPeer().then(function (peerString) {
angular.forEach(peerStrings, function (peerString) { selectedCancel();
var peerID = AppPeersManager.getPeerID(peerString); $rootScope.$broadcast('history_focus', {
AppMessagesManager.forwardMessages(peerID, selectedMessageIDs).then(function () { peerString: peerString,
selectedCancel(); attachment: {
if (peerStrings.length == 1) { _: 'fwd_messages',
$rootScope.$broadcast('history_focus', {peerString: peerString}); id: selectedMessageIDs
} }
});
}); });
}); });
} }
@ -2023,7 +2041,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.$watch('curDialog.peer', resetDraft); $scope.$watch('curDialog.peer', resetDraft);
$scope.$on('user_update', angular.noop); $scope.$on('user_update', angular.noop);
$scope.$on('peer_share', applyShare); $scope.$on('peer_draft_attachment', applyDraftAttachment);
$scope.$on('reply_selected', function (e, messageID) { $scope.$on('reply_selected', function (e, messageID) {
replySelect(messageID); replySelect(messageID);
}); });
@ -2032,7 +2050,8 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.draftMessage = { $scope.draftMessage = {
text: '', text: '',
send: sendMessage, send: sendMessage,
replyClear: replyClear replyClear: replyClear,
fwdsClear: fwdsClear
}; };
$scope.mentions = {}; $scope.mentions = {};
$scope.commands = {}; $scope.commands = {};
@ -2051,6 +2070,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.toggleSlash = toggleSlash; $scope.toggleSlash = toggleSlash;
var replyToMarkup = false; var replyToMarkup = false;
var forceDraft = false;
function sendMessage (e) { function sendMessage (e) {
$scope.$broadcast('ui_message_before_send'); $scope.$broadcast('ui_message_before_send');
@ -2084,6 +2104,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
} while (text.length); } while (text.length);
} }
fwdsSend();
resetDraft(); resetDraft();
$scope.$broadcast('ui_message_send'); $scope.$broadcast('ui_message_send');
@ -2170,6 +2191,19 @@ angular.module('myApp.controllers', ['myApp.i18n'])
replyClear(); replyClear();
updateReplyKeyboard(); updateReplyKeyboard();
// console.log(dT(), 'reset draft', $scope.curDialog.peer, forceDraft);
if (forceDraft) {
if (forceDraft == $scope.curDialog.peer) {
$scope.draftMessage.isBroadcast = AppPeersManager.isChannel($scope.curDialog.peerID);
$scope.$broadcast('ui_peer_draft');
return;
} else {
forceDraft = false;
}
}
fwdsClear();
if (newPeer) { if (newPeer) {
Storage.get('draft' + $scope.curDialog.peerID).then(function (draftText) { Storage.get('draft' + $scope.curDialog.peerID).then(function (draftText) {
// console.log('Restore draft', 'draft' + $scope.curDialog.peerID, draftText); // console.log('Restore draft', 'draft' + $scope.curDialog.peerID, draftText);
@ -2185,20 +2219,33 @@ angular.module('myApp.controllers', ['myApp.i18n'])
} }
} }
function applyShare (e, shareData) { function applyDraftAttachment (e, attachment) {
var url = shareData.url; // console.log('apply draft attach', attachment);
var text = shareData.text || ''; if (!attachment || !attachment._) {
return;
}
$timeout(function () { if (attachment._ == 'share_url') {
$scope.draftMessage.text = url + "\n" + text; var url = attachment.url;
$scope.$broadcast('ui_peer_draft', { var text = attachment.text || '';
customSelection: [ forceDraft = $scope.curDialog.peer;
url + "\n",
text, $timeout(function () {
'' $scope.draftMessage.text = url + "\n" + text;
] $scope.$broadcast('ui_peer_draft', {
}); customSelection: [
}, 1000); url + "\n",
text,
''
]
});
}, 1000);
}
else if (attachment._ == 'fwd_messages') {
forceDraft = $scope.curDialog.peer;
$scope.draftMessage.fwdMessages = attachment.id;
$scope.$broadcast('ui_peer_reply');
}
} }
function replySelect(messageID) { function replySelect(messageID) {
@ -2220,6 +2267,29 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.$broadcast('ui_peer_reply'); $scope.$broadcast('ui_peer_reply');
} }
function fwdsClear () {
if ($scope.draftMessage.fwdMessages &&
$scope.draftMessage.fwdMessages.length) {
delete $scope.draftMessage.fwdMessages;
$scope.$broadcast('ui_peer_reply');
if (forceDraft == $scope.curDialog.peer) {
forceDraft = false;
}
}
}
function fwdsSend () {
if ($scope.draftMessage.fwdMessages &&
$scope.draftMessage.fwdMessages.length) {
var ids = $scope.draftMessage.fwdMessages.slice();
fwdsClear();
setTimeout(function () {
AppMessagesManager.forwardMessages($scope.curDialog.peerID, ids);
}, 0);
}
}
function toggleSlash ($event) { function toggleSlash ($event) {
if ($scope.draftMessage.text && if ($scope.draftMessage.text &&
$scope.draftMessage.text.charAt(0) == '/') { $scope.draftMessage.text.charAt(0) == '/') {
@ -2319,6 +2389,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
AppMessagesManager.sendFile($scope.curDialog.peerID, newVal[i], options); AppMessagesManager.sendFile($scope.curDialog.peerID, newVal[i], options);
$scope.$broadcast('ui_message_send'); $scope.$broadcast('ui_message_send');
} }
fwdsSend();
} }
function onStickerSelected (newVal) { function onStickerSelected (newVal) {
@ -2341,6 +2412,8 @@ angular.module('myApp.controllers', ['myApp.i18n'])
}; };
AppMessagesManager.sendOther($scope.curDialog.peerID, inputMedia, options); AppMessagesManager.sendOther($scope.curDialog.peerID, inputMedia, options);
$scope.$broadcast('ui_message_send'); $scope.$broadcast('ui_message_send');
fwdsSend();
} }
delete $scope.draftMessage.sticker; delete $scope.draftMessage.sticker;
resetDraft(); resetDraft();
@ -2402,14 +2475,14 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.forward = function () { $scope.forward = function () {
var messageID = $scope.messageID; var messageID = $scope.messageID;
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) {
angular.forEach(peerStrings, function (peerString) { PeersSelectService.selectPeer().then(function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString); $rootScope.$broadcast('history_focus', {
AppMessagesManager.forwardMessages(peerID, [messageID]).then(function () { peerString: peerString,
if (peerStrings.length == 1) { attachment: {
$rootScope.$broadcast('history_focus', {peerString: peerString}); _: 'fwd_messages',
} id: [messageID]
}); }
}); });
}); });
}; };
@ -2727,21 +2800,17 @@ angular.module('myApp.controllers', ['myApp.i18n'])
}; };
$scope.forward = function () { $scope.forward = function () {
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) { PeersSelectService.selectPeer({confirm_type: 'FORWARD_PEER'}).then(function (peerString) {
angular.forEach(peerStrings, function (peerString) { var peerID = AppPeersManager.getPeerID(peerString);
var peerID = AppPeersManager.getPeerID(peerString); AppMessagesManager.sendOther(peerID, {
AppMessagesManager.sendOther(peerID, { _: 'inputMediaPhoto',
_: 'inputMediaPhoto', id: {
id: { _: 'inputPhoto',
_: 'inputPhoto', id: $scope.photoID,
id: $scope.photoID, access_hash: $scope.photo.access_hash,
access_hash: $scope.photo.access_hash,
}
});
if (peerStrings.length == 1) {
$rootScope.$broadcast('history_focus', {peerString: peerStrings[0]});
} }
}); });
$rootScope.$broadcast('history_focus', {peerString: peerString});
}); });
}; };
@ -2802,21 +2871,17 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.canDelete = isChannel ? chat.pFlags.creator : true; $scope.canDelete = isChannel ? chat.pFlags.creator : true;
$scope.forward = function () { $scope.forward = function () {
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) { PeersSelectService.selectPeer({confirm_type: 'FORWARD_PEER'}).then(function (peerString) {
angular.forEach(peerStrings, function (peerString) { var peerID = AppPeersManager.getPeerID(peerString);
var peerID = AppPeersManager.getPeerID(peerString); AppMessagesManager.sendOther(peerID, {
AppMessagesManager.sendOther(peerID, { _: 'inputMediaPhoto',
_: 'inputMediaPhoto', id: {
id: { _: 'inputPhoto',
_: 'inputPhoto', id: $scope.photoID,
id: $scope.photoID, access_hash: $scope.photo.access_hash,
access_hash: $scope.photo.access_hash,
}
});
if (peerStrings.length == 1) {
$rootScope.$broadcast('history_focus', {peerString: peerStrings[0]});
} }
}); });
$rootScope.$broadcast('history_focus', {peerString: peerString});
}); });
}; };
@ -2861,14 +2926,13 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.forward = function () { $scope.forward = function () {
var messageID = $scope.messageID; var messageID = $scope.messageID;
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) { PeersSelectService.selectPeer().then(function (peerString) {
angular.forEach(peerStrings, function (peerString) { $rootScope.$broadcast('history_focus', {
var peerID = AppPeersManager.getPeerID(peerString); peerString: peerString,
AppMessagesManager.forwardMessages(peerID, [messageID]).then(function () { attachment: {
if (peerStrings.length == 1) { _: 'fwd_messages',
$rootScope.$broadcast('history_focus', {peerString: peerString}); id: [messageID]
} }
});
}); });
}); });
}; };
@ -2897,14 +2961,13 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.forward = function () { $scope.forward = function () {
var messageID = $scope.messageID; var messageID = $scope.messageID;
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) { PeersSelectService.selectPeer().then(function (peerString) {
angular.forEach(peerStrings, function (peerString) { $rootScope.$broadcast('history_focus', {
var peerID = AppPeersManager.getPeerID(peerString); peerString: peerString,
AppMessagesManager.forwardMessages(peerID, [messageID]).then(function () { attachment: {
if (peerStrings.length == 1) { _: 'fwd_messages',
$rootScope.$broadcast('history_focus', {peerString: peerString}); id: [messageID]
} }
});
}); });
}); });
}; };
@ -2935,14 +2998,13 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.forward = function () { $scope.forward = function () {
var messageID = $scope.messageID; var messageID = $scope.messageID;
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) { PeersSelectService.selectPeer().then(function (peerString) {
angular.forEach(peerStrings, function (peerString) { $rootScope.$broadcast('history_focus', {
var peerID = AppPeersManager.getPeerID(peerString); peerString: peerString,
AppMessagesManager.forwardMessages(peerID, [messageID]).then(function () { attachment: {
if (peerStrings.length == 1) { _: 'fwd_messages',
$rootScope.$broadcast('history_focus', {peerString: peerString}); id: [messageID]
} }
});
}); });
}); });
}; };
@ -3052,20 +3114,16 @@ angular.module('myApp.controllers', ['myApp.i18n'])
}; };
$scope.shareContact = function () { $scope.shareContact = function () {
PeersSelectService.selectPeers({confirm_type: 'SHARE_CONTACT_PEER'}).then(function (peerStrings) { PeersSelectService.selectPeer({confirm_type: 'SHARE_CONTACT_PEER'}).then(function (peerString) {
angular.forEach(peerStrings, function (peerString) { var peerID = AppPeersManager.getPeerID(peerString);
var peerID = AppPeersManager.getPeerID(peerString); AppMessagesManager.sendOther(peerID, {
AppMessagesManager.sendOther(peerID, { _: 'inputMediaContact',
_: 'inputMediaContact', phone_number: $scope.user.phone,
phone_number: $scope.user.phone, first_name: $scope.user.first_name,
first_name: $scope.user.first_name, last_name: $scope.user.last_name,
last_name: $scope.user.last_name, user_id: $scope.user.id
user_id: $scope.user.id
});
if (peerStrings.length == 1) {
$rootScope.$broadcast('history_focus', {peerString: peerStrings[0]});
}
}); });
$rootScope.$broadcast('history_focus', {peerString: peerString});
}); });
} }

View File

@ -379,42 +379,7 @@ angular.module('myApp.directives', ['myApp.filters'])
$(element).remove(); $(element).remove();
return; return;
} }
var thumbWidth = 42; $scope.thumb = AppMessagesManager.getMessageThumb(message, 42, 42);
var thumbHeight = 42;
var thumbPhotoSize;
var sticker = false;
if (message.media) {
switch (message.media._) {
case 'messageMediaPhoto':
thumbPhotoSize = AppPhotosManager.choosePhotoSize(message.media.photo, thumbWidth, thumbHeight);
break;
case 'messageMediaDocument':
thumbPhotoSize = message.media.document.thumb;
if (message.media.document.sticker) {
sticker = true;
}
break;
case 'messageMediaVideo':
thumbPhotoSize = message.media.video.thumb;
break;
}
}
if (thumbPhotoSize && thumbPhotoSize._ != 'photoSizeEmpty') {
var dim = calcImageInBox(thumbPhotoSize.w, thumbPhotoSize.h, thumbWidth, thumbHeight, true);
$scope.thumb = {
width: dim.w,
height: dim.h,
location: thumbPhotoSize.location,
size: thumbPhotoSize.size
};
if (sticker) {
$scope.thumb.location.sticker = true;
}
}
if (element[0].tagName == 'A') { if (element[0].tagName == 'A') {
element.on('click', function () { element.on('click', function () {
@ -433,6 +398,57 @@ angular.module('myApp.directives', ['myApp.filters'])
}) })
.directive('myForwardedMessages', function(AppPhotosManager, AppMessagesManager, AppPeersManager, $rootScope) {
return {
templateUrl: templateUrl('forwarded_messages'),
scope: {
'forwardMessages': '=myForwardedMessages'
},
link: link
};
function link ($scope, element, attrs) {
if (attrs.watch) {
$scope.$watch('forwardMessages', function () {
updateMessages($scope, element);
});
} else {
updateMessages($scope, element);
}
}
function updateMessages ($scope, element) {
var mids = $scope.forwardMessages;
var length = mids.length;
var fromID = false;
var single = length == 1;
$scope.thumb = false;
$scope.singleMessage = false;
angular.forEach(mids, function (mid) {
var message = AppMessagesManager.getMessage(mid);
if (fromID === false) {
fromID = message.fromID;
} else {
if (fromID !== message.fromID) {
fromID = AppMessagesManager.getMessagePeer(message);
}
}
if (single) {
$scope.thumb = AppMessagesManager.getMessageThumb(message, 42, 42);
$scope.singleMessage = AppMessagesManager.wrapForDialog(mid);
}
});
$scope.fromID = fromID;
$scope.count = length;
onContentLoaded(function () {
$scope.$emit('ui_height');
})
}
})
.directive('myMessageText', function(AppPeersManager, AppMessagesManager, AppUsersManager, RichTextProcessor) { .directive('myMessageText', function(AppPeersManager, AppMessagesManager, AppUsersManager, RichTextProcessor) {
return { return {
link: link, link: link,
@ -636,7 +652,6 @@ angular.module('myApp.directives', ['myApp.filters'])
searchField = $('.im_dialogs_search_field', element)[0], searchField = $('.im_dialogs_search_field', element)[0],
panelWrap = $('.im_dialogs_panel', element)[0], panelWrap = $('.im_dialogs_panel', element)[0],
searchClear = $('.im_dialogs_search_clear', element)[0], searchClear = $('.im_dialogs_search_clear', element)[0],
tabsWrap = $('.im_dialogs_tabs_wrap', element)[0],
searchFocused = false; searchFocused = false;
@ -663,12 +678,6 @@ angular.module('myApp.directives', ['myApp.filters'])
$scope.$on('search_clear', function () { $scope.$on('search_clear', function () {
$(panelWrap).removeClass('im_dialogs_panel_search'); $(panelWrap).removeClass('im_dialogs_panel_search');
$scope.$broadcast('ui_dialogs_search'); $scope.$broadcast('ui_dialogs_search');
})
attrs.$observe('hasTabs', function (newValue) {
newValue = newValue == 'true';
$(tabsWrap).toggle(newValue);
$scope.$broadcast('ui_dialogs_tabs', newValue);
}); });
$(document).on('keydown', onKeyDown); $(document).on('keydown', onKeyDown);
@ -828,7 +837,6 @@ angular.module('myApp.directives', ['myApp.filters'])
: '.im_dialogs_panel', : '.im_dialogs_panel',
panelWrap = $(panelWrapSelector)[0], panelWrap = $(panelWrapSelector)[0],
footer = $('.footer_wrap')[0], footer = $('.footer_wrap')[0],
hasTabs = false,
moreNotified = false; moreNotified = false;
onContentLoaded(function () { onContentLoaded(function () {
@ -842,11 +850,6 @@ angular.module('myApp.directives', ['myApp.filters'])
} }
$scope.$on('ui_dialogs_prepend', updateScroller); $scope.$on('ui_dialogs_prepend', updateScroller);
$scope.$on('ui_dialogs_tabs', function (e, newHasTabs) {
hasTabs = newHasTabs;
updateSizes();
});
$scope.$on('ui_dialogs_search', updateSizes); $scope.$on('ui_dialogs_search', updateSizes);
$scope.$on('ui_dialogs_update', updateSizes); $scope.$on('ui_dialogs_update', updateSizes);
@ -891,9 +894,9 @@ angular.module('myApp.directives', ['myApp.filters'])
if (attrs.modal) { if (attrs.modal) {
var height = $($window).height() - var height = $($window).height() -
(panelWrap ? panelWrap.offsetHeight : 58) - (panelWrap ? panelWrap.offsetHeight : 49) -
(Config.Mobile ? 46 : 200); (Config.Mobile ? 46 : 100);
height = Math.min(350, height); height = Math.min(Config.Mobile ? 350 : 450, height);
$(element).css({height: height}); $(element).css({height: height});
updateScroller(); updateScroller();
return; return;

View File

@ -27,13 +27,8 @@ angular.module('myApp.directives')
? '.mobile_modal_body .im_dialogs_panel' ? '.mobile_modal_body .im_dialogs_panel'
: '.im_dialogs_panel', : '.im_dialogs_panel',
panelWrap = $(panelWrapSelector)[0], panelWrap = $(panelWrapSelector)[0],
hasTabs = false,
moreNotified = false; moreNotified = false;
$scope.$on('ui_dialogs_tabs', function (e, newHasTabs) {
hasTabs = newHasTabs;
updateSizes();
});
$scope.$on('ui_dialogs_search', updateSizes); $scope.$on('ui_dialogs_search', updateSizes);
$scope.$on('ui_dialogs_update', updateSizes); $scope.$on('ui_dialogs_update', updateSizes);

View File

@ -348,6 +348,7 @@ function templateUrl (tplName) {
media_modal_layout: 'desktop', media_modal_layout: 'desktop',
slider: 'desktop', slider: 'desktop',
reply_message: 'desktop', reply_message: 'desktop',
forwarded_messages: 'desktop',
chat_invite_link_modal: 'desktop', chat_invite_link_modal: 'desktop',
reply_markup: 'desktop', reply_markup: 'desktop',
dialog_service: 'desktop', dialog_service: 'desktop',

View File

@ -441,6 +441,7 @@
"im_channel_mute": "Mute", "im_channel_mute": "Mute",
"im_channel_unmute": "Unmute", "im_channel_unmute": "Unmute",
"im_reply_loading": "Loading{dots}", "im_reply_loading": "Loading{dots}",
"im_X_forwarded_messages": "{'one': '{} forwarded message', 'other': '{} forwarded messages'}",
"im_photos_drop_text": "Drop photos here to send", "im_photos_drop_text": "Drop photos here to send",
"im_message_field_placeholder": "Write a message...", "im_message_field_placeholder": "Write a message...",
"im_broadcast_field_placeholder": "Broadcast a message...", "im_broadcast_field_placeholder": "Broadcast a message...",

View File

@ -415,6 +415,9 @@ angular.module('myApp.services')
} }
function getMessageLocalID (fullMsgID) { function getMessageLocalID (fullMsgID) {
if (!fullMsgID) {
return 0;
}
return fullMsgID % fullMsgIDModulus; return fullMsgID % fullMsgIDModulus;
} }
@ -1065,119 +1068,118 @@ angular.module('myApp.services')
historyStorage = historiesStorage[peerID] = {count: null, history: [], pending: []}; historyStorage = historiesStorage[peerID] = {count: null, history: [], pending: []};
} }
MtpApiManager.getUserID().then(function (fromID) { var fromID = AppUsersManager.getSelf().id;
if (peerID != fromID) { if (peerID != fromID) {
flags |= 2; flags |= 2;
if (!isChannel && !AppUsersManager.isBot(peerID)) { if (!isChannel && !AppUsersManager.isBot(peerID)) {
flags |= 1; flags |= 1;
}
}
if (replyToMsgID) {
flags |= 8;
}
if (asChannel) {
fromID = 0;
} else {
flags |= 256;
}
message = {
_: 'message',
id: messageID,
from_id: fromID,
to_id: AppPeersManager.getOutputPeer(peerID),
flags: flags,
date: tsNow(true) + serverTimeOffset,
message: text,
random_id: randomIDS,
reply_to_msg_id: replyToMsgID,
entities: entities,
pending: true
};
var toggleError = function (on) {
var historyMessage = messagesForHistory[messageID];
if (on) {
message.error = true;
if (historyMessage) {
historyMessage.error = true;
}
} else {
delete message.error;
if (historyMessage) {
delete historyMessage.error;
} }
} }
$rootScope.$broadcast('messages_pending');
}
message.send = function () {
toggleError(false);
var sentRequestOptions = {};
if (pendingAfterMsgs[peerID]) {
sentRequestOptions.afterMessageID = pendingAfterMsgs[peerID].messageID;
}
var flags = 0;
if (replyToMsgID) { if (replyToMsgID) {
flags |= 1;
}
if (entities.length) {
flags |= 8; flags |= 8;
} }
if (asChannel) { if (asChannel) {
fromID = 0; flags |= 16;
} else {
flags |= 256;
} }
message = { // console.log(flags, entities);
_: 'message', MtpApiManager.invokeApi('messages.sendMessage', {
id: messageID,
from_id: fromID,
to_id: AppPeersManager.getOutputPeer(peerID),
flags: flags, flags: flags,
date: tsNow(true) + serverTimeOffset, peer: inputPeer,
message: text, message: text,
random_id: randomIDS, random_id: randomID,
reply_to_msg_id: replyToMsgID, reply_to_msg_id: getMessageLocalID(replyToMsgID),
entities: entities, entities: entities
pending: true }, sentRequestOptions).then(function (updates) {
}; if (updates._ == 'updateShortSentMessage') {
message.flags = updates.flags;
var toggleError = function (on) { message.date = updates.date;
var historyMessage = messagesForHistory[messageID]; message.id = updates.id;
if (on) { message.media = updates.media;
message.error = true; message.entities = updates.entities;
if (historyMessage) { updates = {
historyMessage.error = true; _: 'updates',
} users: [],
} else { chats: [],
delete message.error; seq: 0,
if (historyMessage) { updates: [{
delete historyMessage.error; _: 'updateMessageID',
} random_id: randomIDS,
id: updates.id
}, {
_: isChannel ? 'updateNewChannelMessage' : 'updateNewMessage',
message: message,
pts: updates.pts,
pts_count: updates.pts_count
}]
};
} }
$rootScope.$broadcast('messages_pending'); ApiUpdatesManager.processUpdateMessage(updates);
} }, function (error) {
toggleError(true);
message.send = function () { })['finally'](function () {
toggleError(false); if (pendingAfterMsgs[peerID] === sentRequestOptions) {
var sentRequestOptions = {}; delete pendingAfterMsgs[peerID];
if (pendingAfterMsgs[peerID]) {
sentRequestOptions.afterMessageID = pendingAfterMsgs[peerID].messageID;
} }
var flags = 0; });
if (replyToMsgID) {
flags |= 1;
}
if (entities.length) {
flags |= 8;
}
if (asChannel) {
flags |= 16;
}
// console.log(flags, entities);
MtpApiManager.invokeApi('messages.sendMessage', {
flags: flags,
peer: inputPeer,
message: text,
random_id: randomID,
reply_to_msg_id: getMessageLocalID(replyToMsgID),
entities: entities
}, sentRequestOptions).then(function (updates) {
if (updates._ == 'updateShortSentMessage') {
message.flags = updates.flags;
message.date = updates.date;
message.id = updates.id;
message.media = updates.media;
message.entities = updates.entities;
updates = {
_: 'updates',
users: [],
chats: [],
seq: 0,
updates: [{
_: 'updateMessageID',
random_id: randomIDS,
id: updates.id
}, {
_: isChannel ? 'updateNewChannelMessage' : 'updateNewMessage',
message: message,
pts: updates.pts,
pts_count: updates.pts_count
}]
};
}
ApiUpdatesManager.processUpdateMessage(updates);
}, function (error) {
toggleError(true);
})['finally'](function () {
if (pendingAfterMsgs[peerID] === sentRequestOptions) {
delete pendingAfterMsgs[peerID];
}
});
pendingAfterMsgs[peerID] = sentRequestOptions; pendingAfterMsgs[peerID] = sentRequestOptions;
}; };
saveMessages([message]); saveMessages([message]);
historyStorage.pending.unshift(messageID); historyStorage.pending.unshift(messageID);
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: true}); $rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: true});
// setTimeout(function () { // setTimeout(function () {
message.send(); message.send();
// }, 5000); // }, 5000);
});
pendingByRandomID[randomIDS] = [peerID, messageID]; pendingByRandomID[randomIDS] = [peerID, messageID];
}; };
@ -1216,151 +1218,150 @@ angular.module('myApp.services')
historyStorage = historiesStorage[peerID] = {count: null, history: [], pending: []}; historyStorage = historiesStorage[peerID] = {count: null, history: [], pending: []};
} }
MtpApiManager.getUserID().then(function (fromID) { var fromID = AppUsersManager.getSelf().id;
if (peerID != fromID) { if (peerID != fromID) {
flags |= 2; flags |= 2;
if (!isChannel && !AppUsersManager.isBot(peerID)) { if (!isChannel && !AppUsersManager.isBot(peerID)) {
flags |= 1; flags |= 1;
}
}
if (replyToMsgID) {
flags |= 8;
}
if (asChannel) {
fromID = 0;
} else {
flags |= 256;
}
var media = {
_: 'messageMediaPending',
type: attachType,
file_name: file.name || apiFileName,
size: file.size,
progress: {percent: 1, total: file.size}
};
var message = {
_: 'message',
id: messageID,
from_id: fromID,
to_id: AppPeersManager.getOutputPeer(peerID),
flags: flags,
date: tsNow(true) + serverTimeOffset,
message: '',
media: media,
random_id: randomIDS,
reply_to_msg_id: replyToMsgID,
pending: true
};
var toggleError = function (on) {
var historyMessage = messagesForHistory[messageID];
if (on) {
message.error = true;
if (historyMessage) {
historyMessage.error = true;
} }
}
if (replyToMsgID) {
flags |= 8;
}
if (asChannel) {
fromID = 0;
} else { } else {
flags |= 256; delete message.error;
} if (historyMessage) {
var media = { delete historyMessage.error;
_: 'messageMediaPending',
type: attachType,
file_name: file.name || apiFileName,
size: file.size,
progress: {percent: 1, total: file.size}
};
var message = {
_: 'message',
id: messageID,
from_id: fromID,
to_id: AppPeersManager.getOutputPeer(peerID),
flags: flags,
date: tsNow(true) + serverTimeOffset,
message: '',
media: media,
random_id: randomIDS,
reply_to_msg_id: replyToMsgID,
pending: true
};
var toggleError = function (on) {
var historyMessage = messagesForHistory[messageID];
if (on) {
message.error = true;
if (historyMessage) {
historyMessage.error = true;
}
} else {
delete message.error;
if (historyMessage) {
delete historyMessage.error;
}
} }
$rootScope.$broadcast('messages_pending');
} }
$rootScope.$broadcast('messages_pending');
}
var uploaded = false, var uploaded = false,
uploadPromise; uploadPromise;
message.send = function () { message.send = function () {
var sendFileDeferred = $q.defer(); var sendFileDeferred = $q.defer();
sendFilePromise.then(function () { sendFilePromise.then(function () {
if (!uploaded || message.error) { if (!uploaded || message.error) {
uploaded = false; uploaded = false;
uploadPromise = MtpApiFileManager.uploadFile(file); uploadPromise = MtpApiFileManager.uploadFile(file);
}
uploadPromise.then(function (inputFile) {
inputFile.name = apiFileName;
uploaded = true;
var inputMedia;
switch (attachType) {
case 'photo':
inputMedia = {_: 'inputMediaUploadedPhoto', file: inputFile};
break;
case 'video':
inputMedia = {_: 'inputMediaUploadedVideo', file: inputFile, duration: 0, w: 0, h: 0, mime_type: file.type};
break;
case 'audio':
inputMedia = {_: 'inputMediaUploadedAudio', file: inputFile, duration: 0, mime_type: file.type};
break;
case 'document':
default:
inputMedia = {_: 'inputMediaUploadedDocument', file: inputFile, mime_type: file.type, attributes: [
{_: 'documentAttributeFilename', file_name: file.name}
]};
} }
var flags = 0;
uploadPromise.then(function (inputFile) { if (replyToMsgID) {
inputFile.name = apiFileName; flags |= 1;
uploaded = true; }
var inputMedia; if (asChannel) {
switch (attachType) { flags |= 16;
case 'photo': }
inputMedia = {_: 'inputMediaUploadedPhoto', file: inputFile}; MtpApiManager.invokeApi('messages.sendMedia', {
break; flags: flags,
peer: inputPeer,
case 'video': media: inputMedia,
inputMedia = {_: 'inputMediaUploadedVideo', file: inputFile, duration: 0, w: 0, h: 0, mime_type: file.type}; random_id: randomID,
break; reply_to_msg_id: getMessageLocalID(replyToMsgID)
}).then(function (updates) {
case 'audio': ApiUpdatesManager.processUpdateMessage(updates);
inputMedia = {_: 'inputMediaUploadedAudio', file: inputFile, duration: 0, mime_type: file.type};
break;
case 'document':
default:
inputMedia = {_: 'inputMediaUploadedDocument', file: inputFile, mime_type: file.type, attributes: [
{_: 'documentAttributeFilename', file_name: file.name}
]};
}
var flags = 0;
if (replyToMsgID) {
flags |= 1;
}
if (asChannel) {
flags |= 16;
}
MtpApiManager.invokeApi('messages.sendMedia', {
flags: flags,
peer: inputPeer,
media: inputMedia,
random_id: randomID,
reply_to_msg_id: getMessageLocalID(replyToMsgID)
}).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
}, function (error) {
if (attachType == 'photo' &&
error.code == 400 &&
error.type == 'PHOTO_INVALID_DIMENSIONS') {
error.handled = true;
attachType = 'document';
message.send();
return;
}
toggleError(true);
});
}, function (error) { }, function (error) {
toggleError(true); if (attachType == 'photo' &&
}, function (progress) { error.code == 400 &&
// console.log('upload progress', progress); error.type == 'PHOTO_INVALID_DIMENSIONS') {
media.progress.done = progress.done; error.handled = true;
media.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total)); attachType = 'document';
$rootScope.$broadcast('history_update', {peerID: peerID}); message.send();
}); return;
media.progress.cancel = function () {
if (!uploaded) {
sendFileDeferred.resolve();
uploadPromise.cancel();
cancelPendingMessage(randomIDS);
} }
} toggleError(true);
uploadPromise['finally'](function () {
sendFileDeferred.resolve();
}); });
}, function (error) {
toggleError(true);
}, function (progress) {
// console.log('upload progress', progress);
media.progress.done = progress.done;
media.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total));
$rootScope.$broadcast('history_update', {peerID: peerID});
}); });
sendFilePromise = sendFileDeferred.promise; media.progress.cancel = function () {
}; if (!uploaded) {
sendFileDeferred.resolve();
uploadPromise.cancel();
cancelPendingMessage(randomIDS);
}
}
saveMessages([message]); uploadPromise['finally'](function () {
historyStorage.pending.unshift(messageID); sendFileDeferred.resolve();
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: true}); });
});
message.send(); sendFilePromise = sendFileDeferred.promise;
}); };
saveMessages([message]);
historyStorage.pending.unshift(messageID);
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: true});
message.send();
pendingByRandomID[randomIDS] = [peerID, messageID]; pendingByRandomID[randomIDS] = [peerID, messageID];
} }
@ -1381,106 +1382,115 @@ angular.module('myApp.services')
historyStorage = historiesStorage[peerID] = {count: null, history: [], pending: []}; historyStorage = historiesStorage[peerID] = {count: null, history: [], pending: []};
} }
MtpApiManager.getUserID().then(function (fromID) { var fromID = AppUsersManager.getSelf().id;
var media; var media;
switch (inputMedia._) { switch (inputMedia._) {
case 'inputMediaContact': case 'inputMediaContact':
media = angular.extend({}, inputMedia, {_: 'messageMediaContact'}); media = angular.extend({}, inputMedia, {_: 'messageMediaContact'});
break; break;
case 'inputMediaPhoto': case 'inputMediaPhoto':
media = { media = {
_: 'messageMediaPhoto', _: 'messageMediaPhoto',
photo: AppPhotosManager.getPhoto(inputMedia.id.id) photo: AppPhotosManager.getPhoto(inputMedia.id.id)
}; };
break; break;
case 'inputMediaDocument': case 'inputMediaDocument':
var doc = AppDocsManager.getDoc(inputMedia.id.id); var doc = AppDocsManager.getDoc(inputMedia.id.id);
if (doc.sticker && doc.stickerSetInput) { if (doc.sticker && doc.stickerSetInput) {
AppStickersManager.pushPopularSticker(doc.id); AppStickersManager.pushPopularSticker(doc.id);
}; };
media = { media = {
_: 'messageMediaDocument', _: 'messageMediaDocument',
'document': doc 'document': doc
}; };
break; break;
}
var flags = 0;
if (peerID != fromID) {
flags |= 2;
if (!AppUsersManager.isBot(peerID)) {
flags |= 1;
} }
}
if (replyToMsgID) {
flags |= 8;
}
if (asChannel) {
fromID = 0;
} else {
flags |= 256;
}
var flags = 0; var message = {
if (peerID != fromID) { _: 'message',
flags |= 2; id: messageID,
if (!AppUsersManager.isBot(peerID)) { from_id: fromID,
flags |= 1; to_id: AppPeersManager.getOutputPeer(peerID),
flags: flags,
date: tsNow(true) + serverTimeOffset,
message: '',
media: media,
random_id: randomIDS,
reply_to_msg_id: replyToMsgID,
pending: true
};
var toggleError = function (on) {
var historyMessage = messagesForHistory[messageID];
if (on) {
message.error = true;
if (historyMessage) {
historyMessage.error = true;
}
} else {
delete message.error;
if (historyMessage) {
delete historyMessage.error;
} }
} }
$rootScope.$broadcast('messages_pending');
}
message.send = function () {
var flags = 0;
if (replyToMsgID) { if (replyToMsgID) {
flags |= 8; flags |= 1;
} }
if (asChannel) { if (asChannel) {
fromID = 0; flags |= 16;
} else {
flags |= 256;
} }
var message = { var sentRequestOptions = {};
_: 'message', if (pendingAfterMsgs[peerID]) {
id: messageID, sentRequestOptions.afterMessageID = pendingAfterMsgs[peerID].messageID;
from_id: fromID, }
to_id: AppPeersManager.getOutputPeer(peerID),
MtpApiManager.invokeApi('messages.sendMedia', {
flags: flags, flags: flags,
date: tsNow(true) + serverTimeOffset, peer: inputPeer,
message: '', media: inputMedia,
media: media, random_id: randomID,
random_id: randomIDS, reply_to_msg_id: getMessageLocalID(replyToMsgID)
reply_to_msg_id: replyToMsgID, }, sentRequestOptions).then(function (updates) {
pending: true ApiUpdatesManager.processUpdateMessage(updates);
}; }, function (error) {
toggleError(true);
var toggleError = function (on) { })['finally'](function () {
var historyMessage = messagesForHistory[messageID]; if (pendingAfterMsgs[peerID] === sentRequestOptions) {
if (on) { delete pendingAfterMsgs[peerID];
message.error = true;
if (historyMessage) {
historyMessage.error = true;
}
} else {
delete message.error;
if (historyMessage) {
delete historyMessage.error;
}
} }
$rootScope.$broadcast('messages_pending'); });
} pendingAfterMsgs[peerID] = sentRequestOptions;
};
message.send = function () { saveMessages([message]);
var flags = 0; historyStorage.pending.unshift(messageID);
if (replyToMsgID) { $rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: true});
flags |= 1;
}
if (asChannel) {
flags |= 16;
}
MtpApiManager.invokeApi('messages.sendMedia', {
flags: flags,
peer: inputPeer,
media: inputMedia,
random_id: randomID,
reply_to_msg_id: getMessageLocalID(replyToMsgID)
}).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
}, function (error) {
toggleError(true);
});
};
saveMessages([message]);
historyStorage.pending.unshift(messageID);
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: true});
message.send();
});
message.send();
pendingByRandomID[randomIDS] = [peerID, messageID]; pendingByRandomID[randomIDS] = [peerID, messageID];
} }
@ -1509,7 +1519,12 @@ angular.module('myApp.services')
to_peer: AppPeersManager.getInputPeerByID(peerID), to_peer: AppPeersManager.getInputPeerByID(peerID),
}, sentRequestOptions).then(function (updates) { }, sentRequestOptions).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates); ApiUpdatesManager.processUpdateMessage(updates);
})['finally'](function () {
if (pendingAfterMsgs[peerID] === sentRequestOptions) {
delete pendingAfterMsgs[peerID];
}
}); });
pendingAfterMsgs[peerID] = sentRequestOptions;
}; };
function startBot (botID, chatID, startParam) { function startBot (botID, chatID, startParam) {
@ -1996,6 +2011,47 @@ angular.module('myApp.services')
return wasUpdated; return wasUpdated;
} }
function getMessageThumb (message, thumbWidth, thumbHeight) {
var thumbPhotoSize;
var sticker = false;
if (message.media) {
switch (message.media._) {
case 'messageMediaPhoto':
thumbPhotoSize = AppPhotosManager.choosePhotoSize(message.media.photo, thumbWidth, thumbHeight);
break;
case 'messageMediaDocument':
thumbPhotoSize = message.media.document.thumb;
if (message.media.document.sticker) {
sticker = true;
}
break;
case 'messageMediaVideo':
thumbPhotoSize = message.media.video.thumb;
break;
}
}
if (thumbPhotoSize && thumbPhotoSize._ != 'photoSizeEmpty') {
var dim = calcImageInBox(thumbPhotoSize.w, thumbPhotoSize.h, thumbWidth, thumbHeight, true);
var thumb = {
width: dim.w,
height: dim.h,
location: thumbPhotoSize.location,
size: thumbPhotoSize.size
};
if (sticker) {
thumb.location.sticker = true;
}
return thumb;
}
return false;
}
function incrementMaxSeenID (maxID) { function incrementMaxSeenID (maxID) {
if (maxSeenID !== false && maxID && maxID > maxSeenID) { if (maxSeenID !== false && maxID && maxID > maxSeenID) {
Storage.set({ Storage.set({
@ -2602,6 +2658,7 @@ angular.module('myApp.services')
startBot: startBot, startBot: startBot,
openChatInviteLink: openChatInviteLink, openChatInviteLink: openChatInviteLink,
getMessagePeer: getMessagePeer, getMessagePeer: getMessagePeer,
getMessageThumb: getMessageThumb,
wrapForDialog: wrapForDialog, wrapForDialog: wrapForDialog,
wrapForHistory: wrapForHistory, wrapForHistory: wrapForHistory,
wrapReplyMarkup: wrapReplyMarkup, wrapReplyMarkup: wrapReplyMarkup,

View File

@ -3794,7 +3794,14 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}).then(function (toPeerString) { }).then(function (toPeerString) {
var url = decodeURIComponent(matches[1]); var url = decodeURIComponent(matches[1]);
var text = matches[2] ? decodeURIComponent(matches[2]) : ''; var text = matches[2] ? decodeURIComponent(matches[2]) : '';
$rootScope.$broadcast('history_focus', {peerString: toPeerString, shareUrl: url, shareText: text}); $rootScope.$broadcast('history_focus', {
peerString: toPeerString,
attachment: {
_: 'share_url',
url: url,
text: text
}
});
}); });
return true; return true;
} }

View File

@ -1055,8 +1055,13 @@ a.tg_radio_on:hover i.icon-radio {
margin-top: 10px; margin-top: 10px;
} }
.im_dialogs_panel { .im_dialogs_panel {
padding: 12px 12px 6px; padding: 12px 12px 12px;
position: relative; position: relative;
.im_dialogs_modal_col_wrap & {
padding: 7px 12px 6px;
.box-shadow(0px 1px 1px rgba(0,0,0,0.15));
z-index: 1;
}
} }
.im_dialogs_search { .im_dialogs_search {
position: relative; position: relative;
@ -1068,7 +1073,7 @@ a.tg_radio_on:hover i.icon-radio {
border: 1px solid #F2F2F2; border: 1px solid #F2F2F2;
border-radius: 2px; border-radius: 2px;
padding: 6px 20px 6px 30px; padding: 6px 20px 6px 30px;
margin: 0 0 6px; margin: 0 0 0;
background-color: #F2F2F2; background-color: #F2F2F2;
.image-2x('../img/icons/IconsetW.png', 42px, 1171px); .image-2x('../img/icons/IconsetW.png', 42px, 1171px);
@ -1076,7 +1081,7 @@ a.tg_radio_on:hover i.icon-radio {
.im_dialogs_modal_col_wrap & { .im_dialogs_modal_col_wrap & {
background-color: #fff; background-color: #fff;
border-color: #d9dbde; border-color: #fff !important;
} }
&:focus, &:focus,
@ -1092,14 +1097,13 @@ a.tg_radio_on:hover i.icon-radio {
a.tg_search_clear { a.tg_search_clear {
position: absolute; position: absolute;
right: 0; right: 0;
margin-top: -40px; margin-top: -34px;
width: 34px; width: 34px;
height: 34px; height: 34px;
opacity: 0.6; opacity: 0.6;
.contacts_modal_search & { .contacts_modal_search & {
right: 12px; right: 12px;
margin-top: -34px;
} }
&:hover { &:hover {
@ -1135,56 +1139,6 @@ i.icon-verified {
} }
.im_dialogs_tabs_wrap {
display: none;
}
.im_dialogs_tabs {
padding: 4px 0;
position: relative;
}
.im_dialogs_tab {
color: #8c8c8c;
background: #f2f2f2;
height: 30px;
text-align: center;
overflow: hidden;
width: 50%;
float: left;
padding: 7px 0;
&:hover,
&:active,
&:focus {
color: #8c8c8c;
text-decoration: none;
}
&.active {
color: #fff;
background: #6490b1;
}
&:first-child {
border-radius: 2px 0 0 2px;
}
&:last-child {
border-radius: 0 2px 2px 0;
}
}
.im_dialogs_panel_dropdown {
position: absolute;
right: 12px;
.dropdown-menu {
right: auto;
left: 0;
margin-top: 8px;
}
}
.im_dialogs_scrollable_wrap { .im_dialogs_scrollable_wrap {
outline: none ! important; outline: none ! important;
@ -1224,6 +1178,10 @@ i.icon-verified {
} }
} }
.im_dialogs_modal_list {
padding-top: 10px;
}
.im_dialog_message_wrap { .im_dialog_message_wrap {
overflow: hidden; overflow: hidden;
word-wrap: break-word; word-wrap: break-word;
@ -3089,14 +3047,16 @@ _:-ms-lang(x), .composer_rich_textarea:empty:focus:before {
/* Contacts modal */ /* Contacts modal */
.contacts_modal_search { .contacts_modal_search {
padding: 0 0 14px;
position: relative; position: relative;
padding: 7px 12px 6px;
.box-shadow(0px 1px 1px rgba(0,0,0,0.15));
z-index: 1;
} }
.contacts_modal_search_field { .contacts_modal_search_field {
font-size: 12px; font-size: 12px;
line-height: normal; line-height: normal;
border: 1px solid #d9dbde; border: 1px solid #fff !important;
border-radius: 2px; border-radius: 2px;
padding: 6px 15px 6px 30px; padding: 6px 15px 6px 30px;
margin: 0; margin: 0;
@ -3130,6 +3090,7 @@ a.contacts_modal_search_clear {
} }
.contacts_modal_members_list { .contacts_modal_members_list {
.contacts_modal_contact_wrap { .contacts_modal_contact_wrap {
margin-top: 0; margin-top: 0;
} }
@ -3395,9 +3356,12 @@ a.contacts_modal_contact:hover .md_modal_list_peer_description,
} }
.im_message_outer_wrap { .im_message_outer_wrap {
background-color: rgba(242, 246, 250, 1.0); // background-color: rgba(242, 246, 250, 1.0);
background-color: rgba(242, 246, 250, 0);
animation-name: im_message_focus_fade; animation-name: im_message_focus_fade;
animation-duration: 5s; -webkit-animation-timing-function: ease-in;
animation-timing-function: ease-out;
animation-duration: 4s;
} }
} }
@ -4088,7 +4052,7 @@ a.countries_modal_search_clear {
padding: 15px 27px 15px; padding: 15px 27px 15px;
} }
.md_modal_footer_empty { .md_modal_footer_empty {
padding: 15px 27px 0; padding: 10px 27px 0;
} }
.md_photo_loading { .md_photo_loading {

View File

@ -622,10 +622,6 @@ a.footer_link.active:active {
-webkit-transform: translateZ(0); -webkit-transform: translateZ(0);
-webkit-perspective: 1000; -webkit-perspective: 1000;
-webkit-backface-visibility: hidden; -webkit-backface-visibility: hidden;
.im_dialogs_modal_col_wrap & {
padding: 0;
}
} }
.im_dialogs_col { .im_dialogs_col {
@ -680,6 +676,7 @@ a.footer_link.active:active {
.contacts_modal_col .nano > & { .contacts_modal_col .nano > & {
width: 5px; width: 5px;
right: 4px; right: 4px;
top: 10px;
} }
.sessions_modal_col .nano > &, .sessions_modal_col .nano > &,
@ -693,6 +690,7 @@ a.footer_link.active:active {
.im_dialogs_modal_col .nano > & { .im_dialogs_modal_col .nano > & {
width: 6px; width: 6px;
right: 2px; right: 2px;
top: 10px;
} }
.im_history_col .nano > & { .im_history_col .nano > & {
@ -777,12 +775,9 @@ a.footer_link.active:active {
} }
} }
&_search {
padding: 15px 12px 12px;
position: relative;
}
&_members_list { &_members_list {
padding-top: 10px;
a.contacts_modal_contact { a.contacts_modal_contact {
padding: 8px 16px; padding: 8px 16px;
} }
@ -1020,9 +1015,6 @@ a.footer_link.active:active {
.modal-dialog { .modal-dialog {
max-width: 420px; max-width: 420px;
} }
.im_dialogs_panel {
padding-top: 15px;
}
} }
&_modal_footer { &_modal_footer {

View File

@ -1512,7 +1512,7 @@ img.composer_user_photo {
.contacts_modal { .contacts_modal {
&_search { &_search {
padding: 3px 0 12px; margin: -9px -9px 0;
} }
&_col { &_col {

View File

@ -0,0 +1,45 @@
<div class="im_message_reply clearfix" ng-class="{im_message_reply_thumbed: thumb !== false}">
<div class="im_message_reply_border"></div>
<div class="im_message_reply_thumb_wrap pull-left" ng-if="thumb !== false">
<img
class="im_message_reply_thumb"
my-load-thumb
thumb="thumb"
watch="true"
/>
</div>
<div class="im_message_reply_author">
<span my-peer-link="fromID" peer-watch="true"></span>
</div>
<div class="im_message_reply_body" ng-switch="singleMessage !== false">
<div ng-switch-when="true">
<span class="im_reply_message_media" ng-if="singleMessage.media" ng-switch="singleMessage.media._">
<span ng-switch-when="messageMediaPhoto" my-i18n="conversation_media_photo"></span>
<span ng-switch-when="messageMediaVideo" my-i18n="conversation_media_video"></span>
<span ng-switch-when="messageMediaDocument" ng-switch="::singleMessage.media.document.sticker || false">
<span ng-switch-when="1" my-i18n="conversation_media_sticker"></span>
<span ng-switch-when="2">
<span ng-bind-html="singleMessage.media.document.stickerEmoji"></span>
(<my-i18n msgid="conversation_media_sticker"></my-i18n>)
</span>
<span ng-switch-default ng-bind="singleMessage.media.document.file_name"></span>
</span>
<span ng-switch-when="messageMediaAudio" my-i18n="conversation_media_audio"></span>
<span ng-switch-when="messageMediaGeo" my-i18n="conversation_media_location"></span>
<span ng-switch-when="messageMediaVenue" my-i18n="conversation_media_location"></span>
<span ng-switch-when="messageMediaContact" my-i18n="conversation_media_contact"></span>
</span>
<span class="im_reply_message_service" ng-if="singleMessage._ == 'messageService'" my-service-short-message="singleMessage"></span>
<span class="im_reply_message_text" ng-if="singleMessage.message.length" ng-bind-html="singleMessage.richMessage"></span>
</div>
<div ng-switch-default>
<span class="im_reply_message_service">
<ng-pluralize count="count"
when="im_X_forwarded_messages">
</ng-pluralize>
</span>
</div>
</div>
</div>

View File

@ -4,7 +4,7 @@
<div class="im_page_split clearfix"> <div class="im_page_split clearfix">
<div class="im_dialogs_col_wrap noselect" ng-controller="AppImDialogsController" my-dialogs has-tabs="{{search.query.length > 0}}" ng-class="search.query.length > 0 ? 'im_dialogs_col_search' : ''"> <div class="im_dialogs_col_wrap noselect" ng-controller="AppImDialogsController" my-dialogs ng-class="search.query.length > 0 ? 'im_dialogs_col_search' : ''">
<div class="im_dialogs_panel"> <div class="im_dialogs_panel">
<div class="im_dialogs_search"> <div class="im_dialogs_search">
<input class="form-control im_dialogs_search_field no_outline" type="search" placeholder="{{'modal_search' | i18n}}" ng-model="search.query"/> <input class="form-control im_dialogs_search_field no_outline" type="search" placeholder="{{'modal_search' | i18n}}" ng-model="search.query"/>
@ -182,6 +182,11 @@
<a class="im_message_reply_wrap" my-reply-message="draftMessage.replyToMessage" watch="true"></a> <a class="im_message_reply_wrap" my-reply-message="draftMessage.replyToMessage" watch="true"></a>
</div> </div>
<div class="im_send_reply_wrap im_send_fwds_wrap" ng-if="draftMessage.fwdMessages.length > 0">
<a class="im_send_reply_cancel" ng-mousedown="draftMessage.fwdsClear()"><i class="icon icon-reply-bar"></i><i class="icon icon-reply-bar"></i></a>
<div class="im_message_reply_wrap" my-forwarded-messages="draftMessage.fwdMessages"></div>
</div>
<div class="im_send_field_wrap" ng-class="historyState.replyKeyboard._ == 'replyKeyboardMarkup' ? 'im_send_field_wrap_2ndbtn' : ''"> <div class="im_send_field_wrap" ng-class="historyState.replyKeyboard._ == 'replyKeyboardMarkup' ? 'im_send_field_wrap_2ndbtn' : ''">
<a class="composer_emoji_insert_btn"><i class="icon icon-emoji"></i></a> <a class="composer_emoji_insert_btn"><i class="icon icon-emoji"></i></a>
<a class="composer_command_btn" ng-show="!historyState.replyKeyboard && commands.list.length > 0 && (!draftMessage.text.length || draftMessage.text[0] == '/')" ng-mousedown="toggleSlash($event)" ng-class="draftMessage.text[0] == '/' ? 'active' : ''"><i class="icon icon-slash"></i></a> <a class="composer_command_btn" ng-show="!historyState.replyKeyboard && commands.list.length > 0 && (!draftMessage.text.length || draftMessage.text[0] == '/')" ng-mousedown="toggleSlash($event)" ng-class="draftMessage.text[0] == '/' ? 'active' : ''"><i class="icon icon-slash"></i></a>

View File

@ -23,7 +23,7 @@
<div my-dialogs-list modal="true" class="im_dialogs_modal_col"> <div my-dialogs-list modal="true" class="im_dialogs_modal_col">
<div class="im_dialogs_wrap nano"> <div class="im_dialogs_wrap nano">
<div class="im_dialogs_scrollable_wrap nano-content"> <div class="im_dialogs_scrollable_wrap nano-content">
<ul class="nav nav-pills nav-stacked"> <ul class="im_dialogs_modal_list nav nav-pills nav-stacked">
<li class="im_dialog_wrap" my-dialog dialog-message="dialogMessage" ng-repeat="dialogMessage in dialogs track by dialogMessage.peerID" ng-class="{active: selectedPeers[dialogMessage.peerID] !== undefined}"></li> <li class="im_dialog_wrap" my-dialog dialog-message="dialogMessage" ng-repeat="dialogMessage in dialogs track by dialogMessage.peerID" ng-class="{active: selectedPeers[dialogMessage.peerID] !== undefined}"></li>
</ul> </ul>
<div class="im_dialogs_contacts_wrap" ng-show="contacts.length > 0"> <div class="im_dialogs_contacts_wrap" ng-show="contacts.length > 0">

View File

@ -1,9 +1,9 @@
<div class="im_message_reply clearfix" ng-class="{im_message_reply_thumbed: thumb != null}" ng-switch="replyMessage.loading"> <div class="im_message_reply clearfix" ng-class="{im_message_reply_thumbed: thumb !== false}" ng-switch="replyMessage.loading">
<div class="im_message_reply_border"></div> <div class="im_message_reply_border"></div>
<div class="im_message_reply_loading" ng-switch-when="true" my-i18n="im_reply_loading"> <div class="im_message_reply_loading" ng-switch-when="true" my-i18n="im_reply_loading">
<my-i18n-param name="dots"><span my-loading-dots></span></my-i18n-param> <my-i18n-param name="dots"><span my-loading-dots></span></my-i18n-param>
</div> </div>
<div class="im_message_reply_thumb_wrap pull-left" ng-if="thumb != null"> <div class="im_message_reply_thumb_wrap pull-left" ng-if="thumb !== false">
<img <img
class="im_message_reply_thumb" class="im_message_reply_thumb"
my-load-thumb my-load-thumb

View File

@ -53,7 +53,7 @@
</li> </li>
</ul> </ul>
<div ng-switch-default ng-switch="historyState.selectActions"> <div ng-switch-default ng-switch="historyState.selectActions">
<ul ng-switch-when="true" class="nav navbar-navbar navbar-quick-nav navbar-history-edit"> <ul ng-switch-when="selected" class="nav navbar-navbar navbar-quick-nav navbar-history-edit">
<li class="navbar-quick-right"> <li class="navbar-quick-right">
<a ng-click="toggleEdit()" my-i18n="modal_cancel"></a> <a ng-click="toggleEdit()" my-i18n="modal_cancel"></a>
</li> </li>

View File

@ -4,7 +4,7 @@
<div class="im_page_split clearfix"> <div class="im_page_split clearfix">
<div ng-controller="AppImDialogsController" my-dialogs has-tabs="{{search.query.length > 0}}" class="im_dialogs_col_wrap" ng-class="search.query.length > 0 ? 'im_dialogs_col_search' : ''"> <div ng-controller="AppImDialogsController" my-dialogs class="im_dialogs_col_wrap" ng-class="search.query.length > 0 ? 'im_dialogs_col_search' : ''">
<div class="im_dialogs_panel"> <div class="im_dialogs_panel">
<div class="im_dialogs_search"> <div class="im_dialogs_search">
<input class="form-control im_dialogs_search_field no_outline" type="search" placeholder="{{'modal_search' | i18n}}" ng-model="search.query"/> <input class="form-control im_dialogs_search_field no_outline" type="search" placeholder="{{'modal_search' | i18n}}" ng-model="search.query"/>
@ -125,10 +125,7 @@
</div> </div>
</div> </div>
<div ng-switch-when="selected" class="im_edit_selected_actions" my-i18n> <div ng-switch-when="selected" class="im_edit_selected_actions" my-i18n>
<a class="btn btn-md btn-md-primary im_edit_cancel_link" ng-click="selectedCancel()" my-i18n="modal_cancel"></a> <a class="btn btn-primary im_edit_forward_btn" ng-click="selectedForward()" ng-class="{disabled: !selectedCount}" ng-disabled="!selectedCount" my-i18n-format="im_forward"></a><a class="btn btn-primary im_edit_delete_btn" ng-click="selectedDelete()" ng-class="{disabled: !selectedCount}" ng-disabled="!selectedCount" my-i18n-format="im_delete" ng-show="historyState.canDelete"></a>
<a class="btn btn-primary im_edit_forward_btn" ng-click="selectedForward()" ng-class="{disabled: !selectedCount}" ng-disabled="!selectedCount" my-i18n-format="im_forward"></a>
<a class="btn btn-primary im_edit_delete_btn" ng-click="selectedDelete()" ng-class="{disabled: !selectedCount}" ng-disabled="!selectedCount" my-i18n-format="im_delete" ng-show="historyState.canDelete"></a>
<a class="btn btn-primary im_edit_reply_btn" ng-click="selectedReply()" ng-show="selectedCount == 1 &amp;&amp; historyState.canReply" my-i18n="im_reply"></a>
<my-i18n-param name="count"><strong class="im_selected_count" ng-show="selectedCount > 0" ng-bind="selectedCount"></strong></my-i18n-param> <my-i18n-param name="count"><strong class="im_selected_count" ng-show="selectedCount > 0" ng-bind="selectedCount"></strong></my-i18n-param>
</div> </div>
</div> </div>
@ -145,6 +142,11 @@
<a class="im_message_reply_wrap" my-reply-message="draftMessage.replyToMessage" watch="true"></a> <a class="im_message_reply_wrap" my-reply-message="draftMessage.replyToMessage" watch="true"></a>
</div> </div>
<div class="im_send_reply_wrap im_send_fwds_wrap" ng-if="draftMessage.fwdMessages.length > 0">
<a class="im_send_reply_cancel" ng-mousedown="draftMessage.fwdsClear()"><i class="icon icon-reply-bar"></i><i class="icon icon-reply-bar"></i></a>
<div class="im_message_reply_wrap" my-forwarded-messages="draftMessage.fwdMessages"></div>
</div>
<div class="im_send_field_panel"> <div class="im_send_field_panel">
<div class="im_send_field_wrap" ng-class="historyState.replyKeyboard._ == 'replyKeyboardMarkup' ? 'im_send_field_wrap_2ndbtn' : ''"> <div class="im_send_field_wrap" ng-class="historyState.replyKeyboard._ == 'replyKeyboardMarkup' ? 'im_send_field_wrap_2ndbtn' : ''">
<a class="composer_command_btn" ng-show="!historyState.replyKeyboard && commands.list.length > 0 && (!draftMessage.text.length || draftMessage.text[0] == '/')" ng-mousedown="toggleSlash($event)" ng-class="draftMessage.text[0] == '/' ? 'active' : ''"><i class="icon icon-slash"></i></a> <a class="composer_command_btn" ng-show="!historyState.replyKeyboard && commands.list.length > 0 && (!draftMessage.text.length || draftMessage.text[0] == '/')" ng-mousedown="toggleSlash($event)" ng-class="draftMessage.text[0] == '/' ? 'active' : ''"><i class="icon icon-slash"></i></a>

View File

@ -24,8 +24,6 @@
</div> </div>
<div ng-switch-default class="im_content_message_wrap" ng-class="::[historyMessage.out ? 'im_message_out' : 'im_message_in', historyMessage.fwdFromID ? 'im_message_fwd' : '']"> <div ng-switch-default class="im_content_message_wrap" ng-class="::[historyMessage.out ? 'im_message_out' : 'im_message_in', historyMessage.fwdFromID ? 'im_message_fwd' : '']">
<i class="icon icon-select-tick"></i>
<i ng-if="::historyMessage.unread &amp;&amp; historyMessage.out || historyMessage.pending || false" class="icon-message-status" ng-class="{'icon-message-status-unread': historyMessage.unread, 'icon-message-status-pending': historyMessage.pending}" ng-show="!historyMessage.error"></i> <i ng-if="::historyMessage.unread &amp;&amp; historyMessage.out || historyMessage.pending || false" class="icon-message-status" ng-class="{'icon-message-status-unread': historyMessage.unread, 'icon-message-status-pending': historyMessage.pending}" ng-show="!historyMessage.error"></i>
<a class="im_message_from_photo pull-left" my-peer-photolink="::historyMessage.fromID" img-class="im_message_from_photo"></a> <a class="im_message_from_photo pull-left" my-peer-photolink="::historyMessage.fromID" img-class="im_message_from_photo"></a>

View File

@ -1,9 +1,9 @@
<div class="message_actions_modal_wrap" my-modal-position> <div class="message_actions_modal_wrap" my-modal-position>
<div class="message_actions_wrap"> <div class="message_actions_wrap">
<button class="btn btn-md btn-md-primary btn-block" my-i18n="message_action_reply" ng-click="$close('reply')"></button> <button ng-if="historyState.canReply" class="btn btn-md btn-md-primary btn-block" my-i18n="message_action_reply" ng-click="$close('reply')"></button>
<button class="btn btn-md btn-md-primary btn-block" my-i18n="message_action_forward" ng-click="$close('forward')"></button> <button class="btn btn-md btn-md-primary btn-block" my-i18n="message_action_forward" ng-click="$close('forward')"></button>
<button class="btn btn-md btn-md-primary btn-block" my-i18n="message_action_delete" ng-click="$close('delete')"></button> <button ng-if="historyState.canDelete" class="btn btn-md btn-md-primary btn-block" my-i18n="message_action_delete" ng-click="$close('delete')"></button>
<button class="btn btn-md btn-md-primary btn-block" my-i18n="message_action_select" ng-click="$close('select')"></button> <button class="btn btn-md btn-md-primary btn-block" my-i18n="message_action_select" ng-click="$close('select')"></button>
<button class="btn btn-md btn-block" my-i18n="message_action_cancel" ng-click="$dismiss()"></button> <button class="btn btn-md btn-block" my-i18n="message_action_cancel" ng-click="$dismiss()"></button>
</div> </div>