Browse Source

Conversation list typing

master
Igor Zhukov 10 years ago
parent
commit
68f3c41003
  1. 34
      app/js/controllers.js
  2. 2
      app/js/locales/en-us.json
  3. 51
      app/js/services.js
  4. 52
      app/partials/desktop/dialog.html
  5. 52
      app/partials/mobile/dialog.html

34
app/js/controllers.js

@ -520,6 +520,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
var jump = 0; var jump = 0;
var contactsJump = 0; var contactsJump = 0;
var peersInDialogs = {}; var peersInDialogs = {};
var typingTimeouts = {};
var contactsShown; var contactsShown;
$scope.$on('dialogs_need_more', function () { $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.$watchCollection('search', function () {
$scope.dialogs = []; $scope.dialogs = [];
$scope.foundMessages = []; $scope.foundMessages = [];

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

@ -317,6 +317,8 @@
"im_one_typing": "{name1} is typing{dots}", "im_one_typing": "{name1} is typing{dots}",
"im_two_typing": "{name1} and {name2} are typing{dots}", "im_two_typing": "{name1} and {name2} are typing{dots}",
"im_many_typing": "{name1}, {name2} and {count} more 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_delete_chat": "Delete Chat",
"im_clear_history": "Clear History", "im_clear_history": "Clear History",
"im_delete": "Delete {count}", "im_delete": "Delete {count}",

51
app/js/services.js

@ -580,7 +580,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} }
return { 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] location: cachedPhotoLocations[id]
}; };
} }
@ -1290,20 +1290,27 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
apiMessage.date -= serverTimeOffset; apiMessage.date -= serverTimeOffset;
if (apiMessage.media && apiMessage.media._ == 'messageMediaPhoto') { if (apiMessage.media) {
AppPhotosManager.savePhoto(apiMessage.media.photo); switch (apiMessage.media._) {
} case 'messageMediaEmpty':
if (apiMessage.media && apiMessage.media._ == 'messageMediaVideo') { delete apiMessage.media;
AppVideoManager.saveVideo(apiMessage.media.video); break;
} case 'messageMediaPhoto':
if (apiMessage.media && apiMessage.media._ == 'messageMediaDocument') { AppPhotosManager.savePhoto(apiMessage.media.photo);
AppDocsManager.saveDoc(apiMessage.media.document); break;
} case 'messageMediaVideo':
if (apiMessage.media && apiMessage.media._ == 'messageMediaAudio') { AppVideoManager.saveVideo(apiMessage.media.video);
AppAudioManager.saveAudio(apiMessage.media.audio); break;
} case 'messageMediaDocument':
if (apiMessage.media && apiMessage.media._ == 'messageMediaUnsupported') { AppDocsManager.saveDoc(apiMessage.media.document);
delete apiMessage.media.bytes; break;
case 'messageMediaAudio':
AppAudioManager.saveAudio(apiMessage.media.audio);
break;
case 'messageMediaUnsupported':
delete apiMessage.media.bytes;
break;
}
} }
if (apiMessage.action && apiMessage.action._ == 'messageActionChatEditPhoto') { if (apiMessage.action && apiMessage.action._ == 'messageActionChatEditPhoto') {
AppPhotosManager.savePhoto(apiMessage.action.photo); AppPhotosManager.savePhoto(apiMessage.action.photo);
@ -1335,7 +1342,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
flags: 3, flags: 3,
date: tsNow(true) + serverTimeOffset, date: tsNow(true) + serverTimeOffset,
message: text, message: text,
media: {_: 'messageMediaEmpty'},
random_id: randomIDS, random_id: randomIDS,
pending: true pending: true
}; };
@ -1813,8 +1819,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var message = angular.copy(messagesStorage[msgID]) || {id: msgID}; var message = angular.copy(messagesStorage[msgID]) || {id: msgID};
message.fromUser = AppUsersManager.getUser(message.from_id);
if (message.chatID = message.to_id.chat_id) { if (message.chatID = message.to_id.chat_id) {
message.peerID = -message.chatID; message.peerID = -message.chatID;
message.peerData = AppChatsManager.getChat(message.chatID); message.peerData = AppChatsManager.getChat(message.chatID);
@ -1878,9 +1882,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
{noLinks: true, noLinebreaks: true} {noLinks: true, noLinebreaks: true}
); );
break; break;
case 'messageMediaEmpty':
delete message.media;
} }
} }
else if (message.action) { else if (message.action) {
@ -2012,7 +2013,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
if (message.message) { if (message.message) {
notificationMessage = RichTextProcessor.wrapPlainText(message.message); notificationMessage = RichTextProcessor.wrapPlainText(message.message);
} else if (message.media && message.media._ != 'messageMediaEmpty') { } else if (message.media) {
switch (message.media._) { switch (message.media._) {
case 'messageMediaPhoto': notificationMessage = _('conversation_media_photo_raw'); break; case 'messageMediaPhoto': notificationMessage = _('conversation_media_photo_raw'); break;
case 'messageMediaVideo': notificationMessage = _('conversation_media_video_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()), to_id: AppPeersManager.getOutputPeer(MtpApiManager.getUserID()),
flags: 1, flags: 1,
date: updateMessage.date, date: updateMessage.date,
message: updateMessage.message, message: updateMessage.message
media: {_: 'messageMediaEmpty'}
}, },
pts: updateMessage.pts pts: updateMessage.pts
}); });
@ -3276,8 +3276,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
to_id: AppPeersManager.getOutputPeer(-updateMessage.chat_id), to_id: AppPeersManager.getOutputPeer(-updateMessage.chat_id),
flags: 1, flags: 1,
date: updateMessage.date, date: updateMessage.date,
message: updateMessage.message, message: updateMessage.message
media: {_: 'messageMediaEmpty'}
}, },
pts: updateMessage.pts pts: updateMessage.pts
}); });

52
app/partials/desktop/dialog.html

@ -1,15 +1,15 @@
<a class="im_dialog" ng-mousedown="dialogSelect(dialogMessage.peerString, dialogMessage.unreadCount == -1 &amp;&amp; dialogMessage.id)"> <a class="im_dialog" ng-mousedown="dialogSelect(dialogMessage.peerString, dialogMessage.unreadCount == -1 && dialogMessage.id)">
<div class="im_dialog_meta pull-right text-right"> <div class="im_dialog_meta pull-right text-right">
<div class="im_dialog_date" ng-bind="dialogMessage.dateText"></div> <div class="im_dialog_date" ng-bind="dialogMessage.dateText"></div>
<span <span
class="im_dialog_badge badge" class="im_dialog_badge badge"
ng-show="dialogMessage.unreadCount > 0 &amp;&amp; !dialogMessage.out" ng-show="dialogMessage.unreadCount > 0 && !dialogMessage.out"
ng-bind="dialogMessage.unreadCount" ng-bind="dialogMessage.unreadCount"
></span> ></span>
<i <i
class="im_dialog_unread" class="im_dialog_unread"
ng-show="dialogMessage.out &amp;&amp; dialogMessage.unread" ng-show="dialogMessage.out && dialogMessage.unread"
></i> ></i>
</div> </div>
@ -17,28 +17,42 @@
<div class="im_dialog_message_wrap"> <div class="im_dialog_message_wrap">
<div class="im_dialog_peer" ng-switch="dialogMessage.peerID > 0"> <div class="im_dialog_peer" ng-switch="::dialogMessage.peerID > 0">
<span class="im_dialog_user" ng-switch-when="true" ng-bind-html="dialogMessage.peerData.rFullName"></span> <span class="im_dialog_user" ng-switch-when="true" my-user-link="dialogMessage.peerID"></span>
<span class="im_dialog_chat" ng-switch-default> <span class="im_dialog_chat" ng-switch-default ng-bind-html="dialogMessage.peerData.rTitle"></span>
<span ng-bind-html="dialogMessage.peerData.rTitle"></span>
</span>
</div> </div>
<div ng-switch="dialogMessage.deleted"> <div ng-if="dialogMessage.typing > 0" class="im_dialog_message" ng-switch="::dialogMessage.peerID > 0" my-i18n>
<span ng-switch-when="true" my-i18n-format="im_conversation_single_typing"></span><span ng-switch-default my-i18n-format="im_conversation_group_typing"></span><my-i18n-param name="name"><span my-user-link="dialogMessage.typing" short="true"></span></my-i18n-param><my-i18n-param name="dots"><span my-loading-dots></span></my-i18n-param>
</div>
<div ng-show="!dialogMessage.typing" ng-switch="dialogMessage.deleted">
<div ng-switch-when="true" class="im_dialog_message"> <div ng-switch-when="true" class="im_dialog_message">
<span class="im_dialog_message_text" my-i18n="conversation_message_deleted"></span> <span class="im_dialog_message_text" my-i18n="conversation_message_deleted"></span>
</div> </div>
<div ng-switch-default class="im_dialog_message"> <div ng-switch-default class="im_dialog_message">
<span class="im_dialog_chat_from_wrap"> <span ng-switch="::dialogMessage.peerID > 0">
<span <span ng-switch-when="true">
class="im_dialog_chat_from" <span class="im_dialog_chat_from_wrap" ng-if="dialogMessage.out">
ng-if="!dialogMessage.out &amp;&amp; dialogMessage.chatID" <span
ng-bind-html="dialogMessage.fromUser.rFirstName" class="im_dialog_chat_from"
></span><span my-i18n="conversation_you"
class="im_dialog_chat_from" ></span><span ng-if="dialogMessage.message.length || dialogMessage.media">:</span>
ng-if="dialogMessage.out" </span>
my-i18n="conversation_you" </span>
></span>{{((dialogMessage.out || dialogMessage.peerID &lt; 0) &amp;&amp; (dialogMessage.message.length || dialogMessage.media &amp;&amp; dialogMessage.media._ != 'messageMediaEmpty')) ? ':' : ''}} <span ng-switch-default>
<span class="im_dialog_chat_from_wrap" ng-switch="dialogMessage.out">
<span
ng-switch-when="false"
class="im_dialog_chat_from"
my-user-link="dialogMessage.from_id" short="true" user-watch="true"
></span><span
ng-switch-when="true"
class="im_dialog_chat_from"
my-i18n="conversation_you"
></span><span ng-if="dialogMessage.message.length || dialogMessage.media">:</span>
</span>
</span>
</span> </span>
<span class="im_dialog_message_media" ng-if="dialogMessage.media" ng-switch="dialogMessage.media._"> <span class="im_dialog_message_media" ng-if="dialogMessage.media" ng-switch="dialogMessage.media._">

52
app/partials/mobile/dialog.html

@ -1,15 +1,15 @@
<a class="im_dialog" ng-mousedown="dialogSelect(dialogMessage.peerString, dialogMessage.unreadCount == -1 &amp;&amp; dialogMessage.id)"> <a class="im_dialog" ng-mousedown="dialogSelect(dialogMessage.peerString, dialogMessage.unreadCount == -1 && dialogMessage.id)">
<div class="im_dialog_meta pull-right text-right"> <div class="im_dialog_meta pull-right text-right">
<div class="im_dialog_date" ng-bind="dialogMessage.dateText"></div> <div class="im_dialog_date" ng-bind="dialogMessage.dateText"></div>
<span <span
class="im_dialog_badge badge" class="im_dialog_badge badge"
ng-show="dialogMessage.unreadCount > 0 &amp;&amp; !dialogMessage.out" ng-show="dialogMessage.unreadCount > 0 && !dialogMessage.out"
ng-bind="dialogMessage.unreadCount" ng-bind="dialogMessage.unreadCount"
></span> ></span>
<i <i
class="im_dialog_unread" class="im_dialog_unread"
ng-show="dialogMessage.out &amp;&amp; dialogMessage.unread" ng-show="dialogMessage.out && dialogMessage.unread"
></i> ></i>
</div> </div>
@ -24,28 +24,42 @@
<div class="im_dialog_message_wrap"> <div class="im_dialog_message_wrap">
<div class="im_dialog_peer" ng-switch="dialogMessage.peerID > 0"> <div class="im_dialog_peer" ng-switch="::dialogMessage.peerID > 0">
<span class="im_dialog_user" ng-switch-when="true" ng-bind-html="dialogMessage.peerData.rFullName"></span> <span class="im_dialog_user" ng-switch-when="true" my-user-link="dialogMessage.peerID"></span>
<span class="im_dialog_chat" ng-switch-default> <span class="im_dialog_chat" ng-switch-default ng-bind-html="dialogMessage.peerData.rTitle"></span>
<span ng-bind-html="dialogMessage.peerData.rTitle"></span>
</span>
</div> </div>
<div ng-switch="dialogMessage.deleted"> <div ng-if="dialogMessage.typing > 0" class="im_dialog_message" ng-switch="::dialogMessage.peerID > 0" my-i18n>
<span ng-switch-when="true" my-i18n-format="im_conversation_single_typing"></span><span ng-switch-default my-i18n-format="im_conversation_group_typing"></span><my-i18n-param name="name"><span my-user-link="dialogMessage.typing" short="true"></span></my-i18n-param><my-i18n-param name="dots"><span my-loading-dots></span></my-i18n-param>
</div>
<div ng-show="!dialogMessage.typing" ng-switch="dialogMessage.deleted">
<div ng-switch-when="true" class="im_dialog_message"> <div ng-switch-when="true" class="im_dialog_message">
<span class="im_dialog_message_text" my-i18n="conversation_message_deleted"></span> <span class="im_dialog_message_text" my-i18n="conversation_message_deleted"></span>
</div> </div>
<div ng-switch-default class="im_dialog_message"> <div ng-switch-default class="im_dialog_message">
<span class="im_dialog_chat_from_wrap"> <span ng-switch="::dialogMessage.peerID > 0">
<span <span ng-switch-when="true">
class="im_dialog_chat_from" <span class="im_dialog_chat_from_wrap" ng-if="dialogMessage.out">
ng-if="!dialogMessage.out &amp;&amp; dialogMessage.chatID" <span
ng-bind-html="dialogMessage.fromUser.rFirstName" class="im_dialog_chat_from"
></span><span my-i18n="conversation_you"
class="im_dialog_chat_from" ></span><span ng-if="dialogMessage.message.length || dialogMessage.media">:</span>
ng-if="dialogMessage.out" </span>
my-i18n="conversation_you" </span>
></span>{{((dialogMessage.out || dialogMessage.peerID &lt; 0) &amp;&amp; (dialogMessage.message.length || dialogMessage.media &amp;&amp; dialogMessage.media._ != 'messageMediaEmpty')) ? ':' : ''}} <span ng-switch-default>
<span class="im_dialog_chat_from_wrap" ng-switch="dialogMessage.out">
<span
ng-switch-when="false"
class="im_dialog_chat_from"
my-user-link="dialogMessage.from_id" short="true" user-watch="true"
></span><span
ng-switch-when="true"
class="im_dialog_chat_from"
my-i18n="conversation_you"
></span><span ng-if="dialogMessage.message.length || dialogMessage.media">:</span>
</span>
</span>
</span> </span>
<span class="im_dialog_message_media" ng-if="dialogMessage.media" ng-switch="dialogMessage.media._"> <span class="im_dialog_message_media" ng-if="dialogMessage.media" ng-switch="dialogMessage.media._">

Loading…
Cancel
Save