Browse Source

Improved message media directives

Improve webpage attach
Improve updates handling
master
Igor Zhukov 9 years ago
parent
commit
29ed4c9997
  1. 84
      app/js/directives.js
  2. 30
      app/js/messages_manager.js
  3. 60
      app/js/services.js
  4. 5
      app/less/app.less
  5. 18
      app/partials/desktop/message.html
  6. 6
      app/partials/desktop/message_attach_webpage.html
  7. 14
      app/partials/desktop/message_media.html

84
app/js/directives.js

@ -176,7 +176,11 @@ angular.module('myApp.directives', ['myApp.filters'])
} }
}) })
.directive('myMessageBody', function(AppPeersManager, AppMessagesManager, AppChatsManager, AppUsersManager, RichTextProcessor) { .directive('myMessageBody', function($compile, AppPeersManager, AppChatsManager, AppUsersManager, AppMessagesManager, RichTextProcessor) {
var messageMediaCompiled = $compile('<div class="im_message_media" my-message-media="media" message-id="messageId"></div>');
var messageKeyboardCompiled = $compile('<div class="im_message_keyboard" my-inline-reply-markup="markup"></div>');
return { return {
link: link, link: link,
scope: { scope: {
@ -184,10 +188,10 @@ angular.module('myApp.directives', ['myApp.filters'])
} }
}; };
function updateMessageText (message, element) { function updateMessageText ($scope, element, message) {
if (typeof message.message !== 'string' || if (typeof message.message !== 'string' ||
!message.message.length) { !message.message.length) {
element.hide(); $('.im_message_text', element).hide();
return; return;
} }
var fromUser = message.from_id && AppUsersManager.getUser(message.from_id); var fromUser = message.from_id && AppUsersManager.getUser(message.from_id);
@ -210,35 +214,66 @@ angular.module('myApp.directives', ['myApp.filters'])
} }
var html = RichTextProcessor.wrapRichText(message.message, options); var html = RichTextProcessor.wrapRichText(message.message, options);
element.html(html.valueOf()); $('.im_message_text', element).html(html.valueOf());
} }
function updateMessageMedia(message, element) { function updateMessageMedia($scope, element, message) {
if (!message.media) { if (!message.media) {
element.hide(); $('.im_message_media', element).hide();
return; return;
} }
switch (message.media._) {
case 'messageMediaPhoto':
var scope = $scope.$new(true);
scope.media = message.media;
scope.messageId = message.mid;
messageMediaCompiled(scope, function (clonedElement) {
$('.im_message_media', element).replaceWith(clonedElement);
});
} }
function updateMessageKeyboard($scope, element, message) {
if (!message.reply_markup ||
message.reply_markup._ != 'replyInlineMarkup') {
$('.im_message_keyboard', element).hide();
return;
}
var scope = $scope.$new(true);
scope.markup = AppMessagesManager.wrapReplyMarkup(message.reply_markup);
scope.messageId = message.mid;
messageKeyboardCompiled(scope, function (clonedElement) {
$('.im_message_keyboard', element).replaceWith(clonedElement);
});
scope.$on('reply_inline_button_press', function (e, button) {
AppMessagesManager.replyMarkupButtonPress(message.mid, button);
});
} }
function link ($scope, element, attrs) { function link ($scope, element, attrs) {
var message = $scope.message; var message = $scope.message;
var msgID = message.mid; var msgID = message.mid;
var textElement = $('.im_message_text', element);
updateMessageText(message, textElement); updateMessageText($scope, element, message);
updateMessageMedia($scope, element, message);
updateMessageKeyboard($scope, element, message);
if (message.pending) { if (message.pending) {
var unlink = $scope.$on('messages_pending', function () { var unlink = $scope.$on('messages_pending', function () {
if (message.mid != msgID) { if (message.mid != msgID) {
updateMessageText(message, textElement); updateMessageText($scope, element, message);
unlink(); unlink();
} }
}) })
} }
$scope.$on('message_edit', function (e, data) {
if (data.mid != msgID) {
return;
}
console.log('after edit', message);
updateMessageKeyboard($scope, element, message);
});
} }
}) })
@ -304,6 +339,15 @@ angular.module('myApp.directives', ['myApp.filters'])
}) })
.directive('myMessageMedia', function() {
return {
scope: {
'media': '=myMessageMedia',
'messageId': '=messageId'
},
templateUrl: templateUrl('message_media')
};
})
.directive('myMessagePhoto', function(AppPhotosManager) { .directive('myMessagePhoto', function(AppPhotosManager) {
return { return {
scope: { scope: {
@ -400,6 +444,24 @@ angular.module('myApp.directives', ['myApp.filters'])
}; };
}) })
.directive('myInlineReplyMarkup', function() {
return {
templateUrl: templateUrl('reply_markup'),
scope: {
'replyMarkup': '=myInlineReplyMarkup'
},
link: link
};
function link ($scope, element, attrs) {
$scope.buttonSend = function (button) {
$scope.$emit('reply_inline_button_press', button);
}
}
})
.directive('myServiceMessage', function() { .directive('myServiceMessage', function() {
return { return {
templateUrl: templateUrl('message_service') templateUrl: templateUrl('message_service')

30
app/js/messages_manager.js

@ -2176,6 +2176,18 @@ angular.module('myApp.services')
return messagesForHistory[msgID] = message; return messagesForHistory[msgID] = message;
} }
function replyMarkupButtonPress(id, button) {
var message = getMessage(id);
var peerID = getMessagePeer(message);
MtpApiManager.invokeApi('messages.getBotCallbackAnswer', {
peer: AppPeersManager.getInputPeerByID(peerID),
msg_id: getMessageLocalID(id),
data: button.data
}).then(function (callbackAnswer) {
console.info(callbackAnswer.message || 'empty answer');
});
}
function wrapReplyMarkup (replyMarkup) { function wrapReplyMarkup (replyMarkup) {
if (!replyMarkup || if (!replyMarkup ||
replyMarkup._ == 'replyKeyboardHide') { replyMarkup._ == 'replyKeyboardHide') {
@ -2184,8 +2196,12 @@ angular.module('myApp.services')
if (replyMarkup.wrapped) { if (replyMarkup.wrapped) {
return replyMarkup; return replyMarkup;
} }
var isInline = replyMarkup._ == 'replyInlineMarkup';
var count = replyMarkup.rows && replyMarkup.rows.length || 0; var count = replyMarkup.rows && replyMarkup.rows.length || 0;
if (count > 0 && count <= 4 && !replyMarkup.pFlags.resize) { if (!isInline &&
count > 0 &&
count <= 4 &&
!(replyMarkup.pFlags && replyMarkup.pFlags.resize)) {
replyMarkup.splitCount = count; replyMarkup.splitCount = count;
} }
replyMarkup.wrapped = true; replyMarkup.wrapped = true;
@ -2193,11 +2209,7 @@ angular.module('myApp.services')
angular.forEach(markupRow.buttons, function (markupButton) { angular.forEach(markupRow.buttons, function (markupButton) {
markupButton.rText = RichTextProcessor.wrapRichText(markupButton.text, {noLinks: true, noLinebreaks: true}); markupButton.rText = RichTextProcessor.wrapRichText(markupButton.text, {noLinks: true, noLinebreaks: true});
}) })
}) });
if (nextRandomInt(1)) {
replyMarkup.rows = replyMarkup.rows.slice(0, 2);
}
return replyMarkup; return replyMarkup;
} }
@ -2788,6 +2800,8 @@ angular.module('myApp.services')
break; break;
} }
console.trace(dT(), 'edit message', mid, message);
saveMessages([message], true); saveMessages([message], true);
safeReplaceObject(messagesStorage[mid], message); safeReplaceObject(messagesStorage[mid], message);
messagesStorage[mid] = message; messagesStorage[mid] = message;
@ -2795,7 +2809,8 @@ angular.module('myApp.services')
if (messagesForHistory[mid] !== undefined) { if (messagesForHistory[mid] !== undefined) {
var wasForHistory = messagesForHistory[mid]; var wasForHistory = messagesForHistory[mid];
delete messagesForHistory[mid]; delete messagesForHistory[mid];
var newForHistory = wrapForHistory(message); var newForHistory = wrapForHistory(mid);
// console.log('replacing', wasForHistory, 'with', newForHistory);
safeReplaceObject(wasForHistory, newForHistory); safeReplaceObject(wasForHistory, newForHistory);
messagesForHistory[mid] = newForHistory; messagesForHistory[mid] = newForHistory;
} }
@ -3081,6 +3096,7 @@ angular.module('myApp.services')
sendOther: sendOther, sendOther: sendOther,
forwardMessages: forwardMessages, forwardMessages: forwardMessages,
startBot: startBot, startBot: startBot,
replyMarkupButtonPress: replyMarkupButtonPress,
openChatInviteLink: openChatInviteLink, openChatInviteLink: openChatInviteLink,
convertMigratedPeer: convertMigratedPeer, convertMigratedPeer: convertMigratedPeer,
getMessagePeer: getMessagePeer, getMessagePeer: getMessagePeer,

60
app/js/services.js

@ -1452,8 +1452,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function wrapForHistory (photoID, options) { function wrapForHistory (photoID, options) {
options = options || {}; options = options || {};
var photo = angular.copy(photos[photoID]) || {_: 'photoEmpty'}, var photo = angular.copy(photos[photoID]) || {_: 'photoEmpty'},
width = options.website ? 100 : Math.min(windowW - 80, Config.Mobile ? 210 : 260), width = options.website ? 64 : Math.min(windowW - 80, Config.Mobile ? 210 : 260),
height = options.website ? 100 : Math.min(windowH - 100, Config.Mobile ? 210 : 260), height = options.website ? 64 : Math.min(windowH - 100, Config.Mobile ? 210 : 260),
thumbPhotoSize = choosePhotoSize(photo, width, height), thumbPhotoSize = choosePhotoSize(photo, width, height),
thumb = { thumb = {
placeholder: 'img/placeholders/PhotoThumbConversation.gif', placeholder: 'img/placeholders/PhotoThumbConversation.gif',
@ -1626,24 +1626,38 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
delete apiWebPage.document; delete apiWebPage.document;
} }
apiWebPage.rTitle = RichTextProcessor.wrapRichText( var siteName = apiWebPage.site_name;
apiWebPage.title || apiWebPage.author, var title = apiWebPage.title || apiWebPage.author || siteName;
{noLinks: true, noLinebreaks: true} if (siteName &&
); title == siteName) {
delete apiWebPage.site_name;
}
apiWebPage.rTitle = RichTextProcessor.wrapRichText(title, {noLinks: true, noLinebreaks: true});
var contextHashtag = ''; var contextHashtag = '';
if (apiWebPage.site_name == 'GitHub') { if (siteName == 'GitHub') {
var matches = apiWebPage.url.match(/(https?:\/\/github\.com\/[^\/]+\/[^\/]+)/); var matches = apiWebPage.url.match(/(https?:\/\/github\.com\/[^\/]+\/[^\/]+)/);
if (matches) { if (matches) {
contextHashtag = matches[0] + '/issues/{1}'; contextHashtag = matches[0] + '/issues/{1}';
} }
} }
// delete apiWebPage.description;
apiWebPage.rDescription = RichTextProcessor.wrapRichText( apiWebPage.rDescription = RichTextProcessor.wrapRichText(
apiWebPage.description, { apiWebPage.description, {
contextSite: apiWebPage.site_name || 'external', contextSite: siteName || 'external',
contextHashtag: contextHashtag contextHashtag: contextHashtag
} }
); );
if (apiWebPage.type != 'photo' &&
apiWebPage.type != 'video' &&
apiWebPage.type != 'gif' &&
apiWebPage.type != 'document' &&
apiWebPage.type != 'gif' &&
!apiWebPage.description &&
apiWebPage.photo) {
apiWebPage.type = 'photo';
}
if (messageID) { if (messageID) {
if (pendingWebPages[apiWebPage.id] === undefined) { if (pendingWebPages[apiWebPage.id] === undefined) {
pendingWebPages[apiWebPage.id] = {}; pendingWebPages[apiWebPage.id] = {};
@ -2966,6 +2980,19 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
break; break;
} }
var curState = channelID ? getChannelState(channelID, update.pts) : updatesState;
// console.log(dT(), 'process', channelID, curState.pts, update);
if (curState.syncLoading) {
return false;
}
if (update._ == 'updateChannelTooLong') {
getChannelDifference(channelID);
return false;
}
if (update._ == 'updateNewMessage' || if (update._ == 'updateNewMessage' ||
update._ == 'updateEditMessage' || update._ == 'updateEditMessage' ||
update._ == 'updateNewChannelMessage' || update._ == 'updateNewChannelMessage' ||
@ -2978,7 +3005,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
fwdHeader.channel_id && !AppChatsManager.hasChat(fwdHeader.channel_id) || fwdHeader.channel_id && !AppChatsManager.hasChat(fwdHeader.channel_id) ||
toPeerID > 0 && !AppUsersManager.hasUser(toPeerID) || toPeerID > 0 && !AppUsersManager.hasUser(toPeerID) ||
toPeerID < 0 && !AppChatsManager.hasChat(-toPeerID)) { toPeerID < 0 && !AppChatsManager.hasChat(-toPeerID)) {
console.warn(dT(), 'Short update not enough data', message); console.warn(dT(), 'Not enough data for message update', message);
if (channelID && AppChatsManager.hasChat(channelID)) { if (channelID && AppChatsManager.hasChat(channelID)) {
getChannelDifference(channelID); getChannelDifference(channelID);
} else { } else {
@ -2987,23 +3014,10 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return false; return false;
} }
} }
else if (channelID && !AppChatsManager.hasChat(channelID)) {
if (channelID && !AppChatsManager.hasChat(channelID)) {
// console.log(dT(), 'skip update, missing channel', channelID, update); // console.log(dT(), 'skip update, missing channel', channelID, update);
return false; return false;
} }
var curState = channelID ? getChannelState(channelID, update.pts) : updatesState;
console.log(dT(), 'process', channelID, curState.pts, update);
if (curState.syncLoading) {
return false;
}
if (update._ == 'updateChannelTooLong') {
getChannelDifference(channelID);
return false;
}
var popPts, popSeq; var popPts, popSeq;

5
app/less/app.less

@ -2255,6 +2255,10 @@ a.im_message_fwd_photo {
.reply_markup_wrap { .reply_markup_wrap {
margin: 15px -2px 0; margin: 15px -2px 0;
.im_message_keyboard & {
margin-top: 7px;
}
} }
.reply_markup_row { .reply_markup_row {
padding: 4px 0; padding: 4px 0;
@ -2296,6 +2300,7 @@ a.im_message_fwd_photo {
height: 36px; height: 36px;
} }
} }
.reply_markup_button:focus,
.reply_markup_button:hover { .reply_markup_button:hover {
color: #3a6d99; color: #3a6d99;
background: #dfe8f0; background: #dfe8f0;

18
app/partials/desktop/message.html

@ -64,22 +64,8 @@
<div my-message-body="historyMessage"> <div my-message-body="historyMessage">
<div class="im_message_text" dir="auto"></div> <div class="im_message_text" dir="auto"></div>
<div class="im_message_media" ng-switch="historyMessage.media._"> <div class="im_message_media"></div>
<div class="im_message_keyboard"></div>
<div ng-switch-when="messageMediaPhoto" my-message-photo="historyMessage.media" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaDocument" my-message-document="historyMessage.media" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaGeo" my-message-geo="historyMessage.media"></div>
<div ng-switch-when="messageMediaVenue" my-message-venue="historyMessage.media"></div>
<div ng-switch-when="messageMediaContact" my-message-contact="historyMessage"></div>
<div ng-switch-when="messageMediaWebPage" my-message-webpage="historyMessage.media" message-id="historyMessage.mid"></div>
<div ng-switch-when="messageMediaPending" my-message-pending="historyMessage.media"></div>
<div ng-switch-when="messageMediaUnsupported">
<div class="im_message_text" my-i18n="message_attach_unsupported">
<my-i18n-param name="link"><a href="https://web.telegram.org" target="_blank">web.telegram.org</a></my-i18n-param>
</div>
</div>
</div>
</div> </div>

6
app/partials/desktop/message_attach_webpage.html

@ -32,14 +32,14 @@
</div> </div>
<div ng-switch-when="document" class="im_message_webpage_document"> <div ng-switch-when="document" class="im_message_webpage_document">
<div my-message-document="webpage" message-id="messageId"></div> <div my-message-document="media.webpage" message-id="messageId"></div>
</div> </div>
<div ng-switch-when="gif" class="im_message_webpage_gif"> <div ng-switch-when="gif" class="im_message_webpage_gif">
<div class="im_message_webpage_title"> <div class="im_message_webpage_title">
<a href="{{media.webpage.url}}" target="_blank" ng-bind-html="media.webpage.rTitle"></a> <a href="{{media.webpage.url}}" target="_blank" ng-bind-html="media.webpage.rTitle"></a>
</div> </div>
<div my-message-document="webpage" message-id="messageId"></div> <div my-message-document="media.webpage" message-id="messageId"></div>
</div> </div>
<div ng-switch-default class="im_message_webpage_article"> <div ng-switch-default class="im_message_webpage_article">
@ -50,7 +50,7 @@
thumb="media.webpage.photo.thumb" thumb="media.webpage.photo.thumb"
/> />
</a> </a>
<div class="im_message_webpage_site" ng-bind="media.webpage.site_name"></div> <div ng-if="media.webpage.site_name" class="im_message_webpage_site" ng-bind="media.webpage.site_name"></div>
<div class="im_message_webpage_title"> <div class="im_message_webpage_title">
<a ng-click="openEmbed($event)" href="{{media.webpage.url}}" target="_blank" ng-bind-html="media.webpage.rTitle"></a> <a ng-click="openEmbed($event)" href="{{media.webpage.url}}" target="_blank" ng-bind-html="media.webpage.rTitle"></a>
</div> </div>

14
app/partials/desktop/message_media.html

@ -0,0 +1,14 @@
<div ng-switch="::media._">
<div ng-switch-when="messageMediaPhoto" my-message-photo="media" message-id="messageId"></div>
<div ng-switch-when="messageMediaDocument" my-message-document="media" message-id="messageId"></div>
<div ng-switch-when="messageMediaGeo" my-message-geo="media"></div>
<div ng-switch-when="messageMediaVenue" my-message-venue="media"></div>
<div ng-switch-when="messageMediaContact" my-message-contact="media"></div>
<div ng-switch-when="messageMediaWebPage" my-message-webpage="media" message-id="messageId"></div>
<div ng-switch-when="messageMediaPending" my-message-pending="media"></div>
<div ng-switch-when="messageMediaUnsupported">
<div class="im_message_text" my-i18n="message_attach_unsupported">
<my-i18n-param name="link"><a href="https://web.telegram.org" target="_blank">web.telegram.org</a></my-i18n-param>
</div>
</div>
</div>
Loading…
Cancel
Save