diff --git a/app/js/controllers.js b/app/js/controllers.js index ed61d6b9..3504db08 100644 --- a/app/js/controllers.js +++ b/app/js/controllers.js @@ -520,6 +520,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) var jump = 0; var contactsJump = 0; var peersInDialogs = {}; + var typingTimeouts = {}; var contactsShown; $scope.$on('dialogs_need_more', function () { @@ -584,6 +585,39 @@ angular.module('myApp.controllers', ['myApp.i18n']) } }); + $scope.$on('apiUpdate', function (e, update) { + switch (update._) { + case 'updateUserTyping': + case 'updateChatUserTyping': + if (!AppUsersManager.hasUser(update.user_id)) { + if (update.chat_id) { + AppChatsManager.getChatFull(update.chat_id); + } + return; + } + var peerID = update._ == 'updateUserTyping'? update.user_id : -update.chat_id; + AppUsersManager.forceUserOnline(update.user_id); + for (var i = 0; i < $scope.dialogs.length; i++) { + if ($scope.dialogs[i].peerID == peerID) { + $scope.dialogs[i].typing = update.user_id; + $timeout.cancel(typingTimeouts[peerID]); + + typingTimeouts[peerID] = $timeout(function () { + for (var i = 0; i < $scope.dialogs.length; i++) { + if ($scope.dialogs[i].peerID == peerID) { + if ($scope.dialogs[i].typing == update.user_id) { + delete $scope.dialogs[i].typing; + } + } + } + }, 6000); + break; + } + } + break; + } + }); + $scope.$watchCollection('search', function () { $scope.dialogs = []; $scope.foundMessages = []; diff --git a/app/js/locales/en-us.json b/app/js/locales/en-us.json index 13669d15..9dd0fdae 100644 --- a/app/js/locales/en-us.json +++ b/app/js/locales/en-us.json @@ -317,6 +317,8 @@ "im_one_typing": "{name1} is typing{dots}", "im_two_typing": "{name1} and {name2} are typing{dots}", "im_many_typing": "{name1}, {name2} and {count} more are typing{dots}", + "im_conversation_single_typing": "typing{dots}", + "im_conversation_group_typing": "{name} is typing{dots}", "im_delete_chat": "Delete Chat", "im_clear_history": "Clear History", "im_delete": "Delete {count}", diff --git a/app/js/services.js b/app/js/services.js index 3650e062..68b12817 100644 --- a/app/js/services.js +++ b/app/js/services.js @@ -580,7 +580,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) } return { - placeholder: 'img/placeholders/' + placeholder + 'Avatar' + chat.num + '@2x.png', + placeholder: 'img/placeholders/' + placeholder + 'Avatar' + (Config.Mobile ? chat.num : Math.ceil(chat.num / 2)) + '@2x.png', location: cachedPhotoLocations[id] }; } @@ -1290,20 +1290,27 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) apiMessage.date -= serverTimeOffset; - if (apiMessage.media && apiMessage.media._ == 'messageMediaPhoto') { - AppPhotosManager.savePhoto(apiMessage.media.photo); - } - if (apiMessage.media && apiMessage.media._ == 'messageMediaVideo') { - AppVideoManager.saveVideo(apiMessage.media.video); - } - if (apiMessage.media && apiMessage.media._ == 'messageMediaDocument') { - AppDocsManager.saveDoc(apiMessage.media.document); - } - if (apiMessage.media && apiMessage.media._ == 'messageMediaAudio') { - AppAudioManager.saveAudio(apiMessage.media.audio); - } - if (apiMessage.media && apiMessage.media._ == 'messageMediaUnsupported') { - delete apiMessage.media.bytes; + if (apiMessage.media) { + switch (apiMessage.media._) { + case 'messageMediaEmpty': + delete apiMessage.media; + break; + case 'messageMediaPhoto': + AppPhotosManager.savePhoto(apiMessage.media.photo); + break; + case 'messageMediaVideo': + AppVideoManager.saveVideo(apiMessage.media.video); + break; + case 'messageMediaDocument': + AppDocsManager.saveDoc(apiMessage.media.document); + break; + case 'messageMediaAudio': + AppAudioManager.saveAudio(apiMessage.media.audio); + break; + case 'messageMediaUnsupported': + delete apiMessage.media.bytes; + break; + } } if (apiMessage.action && apiMessage.action._ == 'messageActionChatEditPhoto') { AppPhotosManager.savePhoto(apiMessage.action.photo); @@ -1335,7 +1342,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) flags: 3, date: tsNow(true) + serverTimeOffset, message: text, - media: {_: 'messageMediaEmpty'}, random_id: randomIDS, pending: true }; @@ -1813,8 +1819,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) var message = angular.copy(messagesStorage[msgID]) || {id: msgID}; - message.fromUser = AppUsersManager.getUser(message.from_id); - if (message.chatID = message.to_id.chat_id) { message.peerID = -message.chatID; message.peerData = AppChatsManager.getChat(message.chatID); @@ -1878,9 +1882,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) {noLinks: true, noLinebreaks: true} ); break; - - case 'messageMediaEmpty': - delete message.media; } } else if (message.action) { @@ -2012,7 +2013,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) if (message.message) { notificationMessage = RichTextProcessor.wrapPlainText(message.message); - } else if (message.media && message.media._ != 'messageMediaEmpty') { + } else if (message.media) { switch (message.media._) { case 'messageMediaPhoto': notificationMessage = _('conversation_media_photo_raw'); break; case 'messageMediaVideo': notificationMessage = _('conversation_media_video_raw'); break; @@ -3253,8 +3254,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) to_id: AppPeersManager.getOutputPeer(MtpApiManager.getUserID()), flags: 1, date: updateMessage.date, - message: updateMessage.message, - media: {_: 'messageMediaEmpty'} + message: updateMessage.message }, pts: updateMessage.pts }); @@ -3276,8 +3276,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) to_id: AppPeersManager.getOutputPeer(-updateMessage.chat_id), flags: 1, date: updateMessage.date, - message: updateMessage.message, - media: {_: 'messageMediaEmpty'} + message: updateMessage.message }, pts: updateMessage.pts }); diff --git a/app/partials/desktop/dialog.html b/app/partials/desktop/dialog.html index d23efda7..84ffb6f0 100644 --- a/app/partials/desktop/dialog.html +++ b/app/partials/desktop/dialog.html @@ -1,15 +1,15 @@ - +
@@ -17,28 +17,42 @@
-
- - - - +
+ +
-
+
+ +
+ +