Browse Source

New forward messages

master
Igor Zhukov 9 years ago
parent
commit
7d77145ebb
  1. 274
      app/js/controllers.js
  2. 107
      app/js/directives.js
  3. 5
      app/js/directives_mobile.js
  4. 1
      app/js/lib/utils.js
  5. 1
      app/js/locales/en-us.json
  6. 671
      app/js/messages_manager.js
  7. 9
      app/js/services.js
  8. 84
      app/less/app.less
  9. 16
      app/less/desktop.less
  10. 2
      app/less/mobile.less
  11. 45
      app/partials/desktop/forwarded_messages.html
  12. 7
      app/partials/desktop/im.html
  13. 2
      app/partials/desktop/peer_select.html
  14. 4
      app/partials/desktop/reply_message.html
  15. 2
      app/partials/mobile/head.html
  16. 12
      app/partials/mobile/im.html
  17. 2
      app/partials/mobile/message.html
  18. 4
      app/partials/mobile/message_actions_modal.html

274
app/js/controllers.js

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

107
app/js/directives.js

@ -379,42 +379,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -379,42 +379,7 @@ angular.module('myApp.directives', ['myApp.filters'])
$(element).remove();
return;
}
var thumbWidth = 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;
}
}
$scope.thumb = AppMessagesManager.getMessageThumb(message, 42, 42);
if (element[0].tagName == 'A') {
element.on('click', function () {
@ -433,6 +398,57 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -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) {
return {
link: link,
@ -636,7 +652,6 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -636,7 +652,6 @@ angular.module('myApp.directives', ['myApp.filters'])
searchField = $('.im_dialogs_search_field', element)[0],
panelWrap = $('.im_dialogs_panel', element)[0],
searchClear = $('.im_dialogs_search_clear', element)[0],
tabsWrap = $('.im_dialogs_tabs_wrap', element)[0],
searchFocused = false;
@ -663,12 +678,6 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -663,12 +678,6 @@ angular.module('myApp.directives', ['myApp.filters'])
$scope.$on('search_clear', function () {
$(panelWrap).removeClass('im_dialogs_panel_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);
@ -828,7 +837,6 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -828,7 +837,6 @@ angular.module('myApp.directives', ['myApp.filters'])
: '.im_dialogs_panel',
panelWrap = $(panelWrapSelector)[0],
footer = $('.footer_wrap')[0],
hasTabs = false,
moreNotified = false;
onContentLoaded(function () {
@ -842,11 +850,6 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -842,11 +850,6 @@ angular.module('myApp.directives', ['myApp.filters'])
}
$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_update', updateSizes);
@ -891,9 +894,9 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -891,9 +894,9 @@ angular.module('myApp.directives', ['myApp.filters'])
if (attrs.modal) {
var height = $($window).height() -
(panelWrap ? panelWrap.offsetHeight : 58) -
(Config.Mobile ? 46 : 200);
height = Math.min(350, height);
(panelWrap ? panelWrap.offsetHeight : 49) -
(Config.Mobile ? 46 : 100);
height = Math.min(Config.Mobile ? 350 : 450, height);
$(element).css({height: height});
updateScroller();
return;

5
app/js/directives_mobile.js

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

1
app/js/lib/utils.js

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

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

@ -441,6 +441,7 @@ @@ -441,6 +441,7 @@
"im_channel_mute": "Mute",
"im_channel_unmute": "Unmute",
"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_message_field_placeholder": "Write a message...",
"im_broadcast_field_placeholder": "Broadcast a message...",

671
app/js/messages_manager.js

@ -415,6 +415,9 @@ angular.module('myApp.services') @@ -415,6 +415,9 @@ angular.module('myApp.services')
}
function getMessageLocalID (fullMsgID) {
if (!fullMsgID) {
return 0;
}
return fullMsgID % fullMsgIDModulus;
}
@ -1065,119 +1068,118 @@ angular.module('myApp.services') @@ -1065,119 +1068,118 @@ angular.module('myApp.services')
historyStorage = historiesStorage[peerID] = {count: null, history: [], pending: []};
}
MtpApiManager.getUserID().then(function (fromID) {
if (peerID != fromID) {
flags |= 2;
if (!isChannel && !AppUsersManager.isBot(peerID)) {
flags |= 1;
var fromID = AppUsersManager.getSelf().id;
if (peerID != fromID) {
flags |= 2;
if (!isChannel && !AppUsersManager.isBot(peerID)) {
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) {
flags |= 1;
}
if (entities.length) {
flags |= 8;
}
if (asChannel) {
fromID = 0;
} else {
flags |= 256;
flags |= 16;
}
message = {
_: 'message',
id: messageID,
from_id: fromID,
to_id: AppPeersManager.getOutputPeer(peerID),
// console.log(flags, entities);
MtpApiManager.invokeApi('messages.sendMessage', {
flags: flags,
date: tsNow(true) + serverTimeOffset,
peer: inputPeer,
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;
}
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
}]
};
}
$rootScope.$broadcast('messages_pending');
}
message.send = function () {
toggleError(false);
var sentRequestOptions = {};
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];
}
});
ApiUpdatesManager.processUpdateMessage(updates);
}, function (error) {
toggleError(true);
})['finally'](function () {
if (pendingAfterMsgs[peerID] === sentRequestOptions) {
delete pendingAfterMsgs[peerID];
}
});
pendingAfterMsgs[peerID] = sentRequestOptions;
};
pendingAfterMsgs[peerID] = sentRequestOptions;
};
saveMessages([message]);
historyStorage.pending.unshift(messageID);
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: true});
saveMessages([message]);
historyStorage.pending.unshift(messageID);
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: true});
// setTimeout(function () {
message.send();
// }, 5000);
});
// setTimeout(function () {
message.send();
// }, 5000);
pendingByRandomID[randomIDS] = [peerID, messageID];
};
@ -1216,151 +1218,150 @@ angular.module('myApp.services') @@ -1216,151 +1218,150 @@ angular.module('myApp.services')
historyStorage = historiesStorage[peerID] = {count: null, history: [], pending: []};
}
MtpApiManager.getUserID().then(function (fromID) {
if (peerID != fromID) {
flags |= 2;
if (!isChannel && !AppUsersManager.isBot(peerID)) {
flags |= 1;
}
}
if (replyToMsgID) {
flags |= 8;
var fromID = AppUsersManager.getSelf().id;
if (peerID != fromID) {
flags |= 2;
if (!isChannel && !AppUsersManager.isBot(peerID)) {
flags |= 1;
}
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}
};
}
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 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;
}
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,
uploadPromise;
var uploaded = false,
uploadPromise;
message.send = function () {
var sendFileDeferred = $q.defer();
message.send = function () {
var sendFileDeferred = $q.defer();
sendFilePromise.then(function () {
if (!uploaded || message.error) {
uploaded = false;
uploadPromise = MtpApiFileManager.uploadFile(file);
}
sendFilePromise.then(function () {
if (!uploaded || message.error) {
uploaded = false;
uploadPromise = MtpApiFileManager.uploadFile(file);
}
uploadPromise.then(function (inputFile) {
inputFile.name = apiFileName;
uploaded = true;
var inputMedia;
switch (attachType) {
case 'photo':
inputMedia = {_: 'inputMediaUploadedPhoto', file: inputFile};
break;
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 '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 '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;
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);
});
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 (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});
});
}, 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});
});
media.progress.cancel = function () {
if (!uploaded) {
sendFileDeferred.resolve();
uploadPromise.cancel();
cancelPendingMessage(randomIDS);
}
media.progress.cancel = function () {
if (!uploaded) {
sendFileDeferred.resolve();
uploadPromise.cancel();
cancelPendingMessage(randomIDS);
}
}
uploadPromise['finally'](function () {
sendFileDeferred.resolve();
});
uploadPromise['finally'](function () {
sendFileDeferred.resolve();
});
});
sendFilePromise = sendFileDeferred.promise;
};
sendFilePromise = sendFileDeferred.promise;
};
saveMessages([message]);
historyStorage.pending.unshift(messageID);
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: 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];
}
@ -1381,106 +1382,115 @@ angular.module('myApp.services') @@ -1381,106 +1382,115 @@ angular.module('myApp.services')
historyStorage = historiesStorage[peerID] = {count: null, history: [], pending: []};
}
MtpApiManager.getUserID().then(function (fromID) {
var media;
switch (inputMedia._) {
case 'inputMediaContact':
media = angular.extend({}, inputMedia, {_: 'messageMediaContact'});
break;
var fromID = AppUsersManager.getSelf().id;
var media;
switch (inputMedia._) {
case 'inputMediaContact':
media = angular.extend({}, inputMedia, {_: 'messageMediaContact'});
break;
case 'inputMediaPhoto':
media = {
_: 'messageMediaPhoto',
photo: AppPhotosManager.getPhoto(inputMedia.id.id)
};
break;
case 'inputMediaPhoto':
media = {
_: 'messageMediaPhoto',
photo: AppPhotosManager.getPhoto(inputMedia.id.id)
};
break;
case 'inputMediaDocument':
var doc = AppDocsManager.getDoc(inputMedia.id.id);
if (doc.sticker && doc.stickerSetInput) {
AppStickersManager.pushPopularSticker(doc.id);
};
media = {
_: 'messageMediaDocument',
'document': doc
};
break;
case 'inputMediaDocument':
var doc = AppDocsManager.getDoc(inputMedia.id.id);
if (doc.sticker && doc.stickerSetInput) {
AppStickersManager.pushPopularSticker(doc.id);
};
media = {
_: 'messageMediaDocument',
'document': doc
};
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;
if (peerID != fromID) {
flags |= 2;
if (!AppUsersManager.isBot(peerID)) {
flags |= 1;
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');
}
message.send = function () {
var flags = 0;
if (replyToMsgID) {
flags |= 8;
flags |= 1;
}
if (asChannel) {
fromID = 0;
} else {
flags |= 256;
flags |= 16;
}
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');
var sentRequestOptions = {};
if (pendingAfterMsgs[peerID]) {
sentRequestOptions.afterMessageID = pendingAfterMsgs[peerID].messageID;
}
message.send = function () {
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)
}, sentRequestOptions).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
}, function (error) {
toggleError(true);
})['finally'](function () {
if (pendingAfterMsgs[peerID] === sentRequestOptions) {
delete pendingAfterMsgs[peerID];
}
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);
});
};
});
pendingAfterMsgs[peerID] = sentRequestOptions;
};
saveMessages([message]);
historyStorage.pending.unshift(messageID);
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: true});
message.send();
});
saveMessages([message]);
historyStorage.pending.unshift(messageID);
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: true});
message.send();
pendingByRandomID[randomIDS] = [peerID, messageID];
}
@ -1509,7 +1519,12 @@ angular.module('myApp.services') @@ -1509,7 +1519,12 @@ angular.module('myApp.services')
to_peer: AppPeersManager.getInputPeerByID(peerID),
}, sentRequestOptions).then(function (updates) {
ApiUpdatesManager.processUpdateMessage(updates);
})['finally'](function () {
if (pendingAfterMsgs[peerID] === sentRequestOptions) {
delete pendingAfterMsgs[peerID];
}
});
pendingAfterMsgs[peerID] = sentRequestOptions;
};
function startBot (botID, chatID, startParam) {
@ -1996,6 +2011,47 @@ angular.module('myApp.services') @@ -1996,6 +2011,47 @@ angular.module('myApp.services')
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) {
if (maxSeenID !== false && maxID && maxID > maxSeenID) {
Storage.set({
@ -2602,6 +2658,7 @@ angular.module('myApp.services') @@ -2602,6 +2658,7 @@ angular.module('myApp.services')
startBot: startBot,
openChatInviteLink: openChatInviteLink,
getMessagePeer: getMessagePeer,
getMessageThumb: getMessageThumb,
wrapForDialog: wrapForDialog,
wrapForHistory: wrapForHistory,
wrapReplyMarkup: wrapReplyMarkup,

9
app/js/services.js

@ -3794,7 +3794,14 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -3794,7 +3794,14 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}).then(function (toPeerString) {
var url = decodeURIComponent(matches[1]);
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;
}

84
app/less/app.less

@ -1055,8 +1055,13 @@ a.tg_radio_on:hover i.icon-radio { @@ -1055,8 +1055,13 @@ a.tg_radio_on:hover i.icon-radio {
margin-top: 10px;
}
.im_dialogs_panel {
padding: 12px 12px 6px;
padding: 12px 12px 12px;
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 {
position: relative;
@ -1068,7 +1073,7 @@ a.tg_radio_on:hover i.icon-radio { @@ -1068,7 +1073,7 @@ a.tg_radio_on:hover i.icon-radio {
border: 1px solid #F2F2F2;
border-radius: 2px;
padding: 6px 20px 6px 30px;
margin: 0 0 6px;
margin: 0 0 0;
background-color: #F2F2F2;
.image-2x('../img/icons/IconsetW.png', 42px, 1171px);
@ -1076,7 +1081,7 @@ a.tg_radio_on:hover i.icon-radio { @@ -1076,7 +1081,7 @@ a.tg_radio_on:hover i.icon-radio {
.im_dialogs_modal_col_wrap & {
background-color: #fff;
border-color: #d9dbde;
border-color: #fff !important;
}
&:focus,
@ -1092,14 +1097,13 @@ a.tg_radio_on:hover i.icon-radio { @@ -1092,14 +1097,13 @@ a.tg_radio_on:hover i.icon-radio {
a.tg_search_clear {
position: absolute;
right: 0;
margin-top: -40px;
margin-top: -34px;
width: 34px;
height: 34px;
opacity: 0.6;
.contacts_modal_search & {
right: 12px;
margin-top: -34px;
}
&:hover {
@ -1135,56 +1139,6 @@ i.icon-verified { @@ -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 {
outline: none ! important;
@ -1224,6 +1178,10 @@ i.icon-verified { @@ -1224,6 +1178,10 @@ i.icon-verified {
}
}
.im_dialogs_modal_list {
padding-top: 10px;
}
.im_dialog_message_wrap {
overflow: hidden;
word-wrap: break-word;
@ -3089,14 +3047,16 @@ _:-ms-lang(x), .composer_rich_textarea:empty:focus:before { @@ -3089,14 +3047,16 @@ _:-ms-lang(x), .composer_rich_textarea:empty:focus:before {
/* Contacts modal */
.contacts_modal_search {
padding: 0 0 14px;
position: relative;
padding: 7px 12px 6px;
.box-shadow(0px 1px 1px rgba(0,0,0,0.15));
z-index: 1;
}
.contacts_modal_search_field {
font-size: 12px;
line-height: normal;
border: 1px solid #d9dbde;
border: 1px solid #fff !important;
border-radius: 2px;
padding: 6px 15px 6px 30px;
margin: 0;
@ -3130,6 +3090,7 @@ a.contacts_modal_search_clear { @@ -3130,6 +3090,7 @@ a.contacts_modal_search_clear {
}
.contacts_modal_members_list {
.contacts_modal_contact_wrap {
margin-top: 0;
}
@ -3395,9 +3356,12 @@ a.contacts_modal_contact:hover .md_modal_list_peer_description, @@ -3395,9 +3356,12 @@ a.contacts_modal_contact:hover .md_modal_list_peer_description,
}
.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-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 { @@ -4088,7 +4052,7 @@ a.countries_modal_search_clear {
padding: 15px 27px 15px;
}
.md_modal_footer_empty {
padding: 15px 27px 0;
padding: 10px 27px 0;
}
.md_photo_loading {

16
app/less/desktop.less

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

2
app/less/mobile.less

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

45
app/partials/desktop/forwarded_messages.html

@ -0,0 +1,45 @@ @@ -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>

7
app/partials/desktop/im.html

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
<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_search">
<input class="form-control im_dialogs_search_field no_outline" type="search" placeholder="{{'modal_search' | i18n}}" ng-model="search.query"/>
@ -182,6 +182,11 @@ @@ -182,6 +182,11 @@
<a class="im_message_reply_wrap" my-reply-message="draftMessage.replyToMessage" watch="true"></a>
</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' : ''">
<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>

2
app/partials/desktop/peer_select.html

@ -23,7 +23,7 @@ @@ -23,7 +23,7 @@
<div my-dialogs-list modal="true" class="im_dialogs_modal_col">
<div class="im_dialogs_wrap nano">
<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>
</ul>
<div class="im_dialogs_contacts_wrap" ng-show="contacts.length > 0">

4
app/partials/desktop/reply_message.html

@ -1,9 +1,9 @@ @@ -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_loading" ng-switch-when="true" my-i18n="im_reply_loading">
<my-i18n-param name="dots"><span my-loading-dots></span></my-i18n-param>
</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
class="im_message_reply_thumb"
my-load-thumb

2
app/partials/mobile/head.html

@ -53,7 +53,7 @@ @@ -53,7 +53,7 @@
</li>
</ul>
<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">
<a ng-click="toggleEdit()" my-i18n="modal_cancel"></a>
</li>

12
app/partials/mobile/im.html

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
<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_search">
<input class="form-control im_dialogs_search_field no_outline" type="search" placeholder="{{'modal_search' | i18n}}" ng-model="search.query"/>
@ -125,10 +125,7 @@ @@ -125,10 +125,7 @@
</div>
</div>
<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_reply_btn" ng-click="selectedReply()" ng-show="selectedCount == 1 &amp;&amp; historyState.canReply" my-i18n="im_reply"></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>
<my-i18n-param name="count"><strong class="im_selected_count" ng-show="selectedCount > 0" ng-bind="selectedCount"></strong></my-i18n-param>
</div>
</div>
@ -145,6 +142,11 @@ @@ -145,6 +142,11 @@
<a class="im_message_reply_wrap" my-reply-message="draftMessage.replyToMessage" watch="true"></a>
</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_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>

2
app/partials/mobile/message.html

@ -24,8 +24,6 @@ @@ -24,8 +24,6 @@
</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' : '']">
<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>
<a class="im_message_from_photo pull-left" my-peer-photolink="::historyMessage.fromID" img-class="im_message_from_photo"></a>

4
app/partials/mobile/message_actions_modal.html

@ -1,9 +1,9 @@ @@ -1,9 +1,9 @@
<div class="message_actions_modal_wrap" my-modal-position>
<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_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-block" my-i18n="message_action_cancel" ng-click="$dismiss()"></button>
</div>

Loading…
Cancel
Save