diff --git a/app/js/controllers.js b/app/js/controllers.js index ff34028c..04e1a9fc 100644 --- a/app/js/controllers.js +++ b/app/js/controllers.js @@ -746,8 +746,26 @@ angular.module('myApp.controllers', ['myApp.i18n']) } } - $scope.$on('dialog_flush', function (e, dialog) { - deleteDialog(dialog.peerID); + $scope.$on('dialog_top', function (e, dialog) { + var curDialog, i; + for (i = 0; i < $scope.dialogs.length; i++) { + curDialog = $scope.dialogs[i]; + if (curDialog.peerID == dialog.peerID) { + var wrappedDialog = AppMessagesManager.wrapForDialog(dialog.top_message, dialog); + $scope.dialogs.splice(i, 1, wrappedDialog); + break; + } + } + }); + $scope.$on('dialog_flush', function (e, update) { + var curDialog, i; + for (i = 0; i < $scope.dialogs.length; i++) { + curDialog = $scope.dialogs[i]; + if (curDialog.peerID == update.peerID) { + curDialog.deleted = true; + break; + } + } }); $scope.$on('dialog_drop', function (e, dialog) { deleteDialog(dialog.peerID); @@ -1695,7 +1713,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) function selectedFlush () { ErrorService.confirm({type: 'HISTORY_FLUSH'}).then(function () { - AppMessagesManager.flushHistory($scope.curDialog.peerID).then(function () { + AppMessagesManager.flushHistory($scope.curDialog.peerID, true).then(function () { selectedCancel(); }); }) @@ -2645,6 +2663,8 @@ angular.module('myApp.controllers', ['myApp.i18n']) MtpApiManager.invokeApi('messages.setTyping', { peer: AppPeersManager.getInputPeerByID($scope.curDialog.peerID), action: {_: 'sendMessageTypingAction'} + })['catch'](function (error) { + error.handled = true; }); } @@ -3324,7 +3344,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) }) - .controller('UserModalController', function ($scope, $location, $rootScope, AppProfileManager, $modal, AppUsersManager, MtpApiManager, NotificationsManager, AppPhotosManager, AppMessagesManager, AppPeersManager, PeersSelectService, ErrorService) { + .controller('UserModalController', function ($scope, $location, $rootScope, $modalInstance, AppProfileManager, $modal, AppUsersManager, MtpApiManager, NotificationsManager, AppPhotosManager, AppMessagesManager, AppPeersManager, PeersSelectService, ErrorService) { var peerString = AppUsersManager.getUserString($scope.userID); @@ -3358,10 +3378,15 @@ angular.module('myApp.controllers', ['myApp.i18n']) $rootScope.$broadcast('history_focus', {peerString: peerString}); }; - $scope.flushHistory = function () { - ErrorService.confirm({type: 'HISTORY_FLUSH'}).then(function () { - AppMessagesManager.flushHistory($scope.userID).then(function () { - $scope.goToHistory(); + $scope.flushHistory = function (justClear) { + ErrorService.confirm({type: justClear ? 'HISTORY_FLUSH' : 'HISTORY_FLUSH_AND_DELETE'}).then(function () { + AppMessagesManager.flushHistory($scope.userID, justClear).then(function () { + if (justClear) { + $scope.goToHistory(); + } else { + $modalInstance.close(); + $location.url('/im'); + } }); }); }; @@ -3436,7 +3461,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) }) - .controller('ChatModalController', function ($scope, $timeout, $rootScope, $modal, AppUsersManager, AppChatsManager, AppProfileManager, AppPhotosManager, MtpApiManager, MtpApiFileManager, NotificationsManager, AppMessagesManager, AppPeersManager, ApiUpdatesManager, ContactsSelectService, ErrorService) { + .controller('ChatModalController', function ($scope, $modalInstance, $location, $timeout, $rootScope, $modal, AppUsersManager, AppChatsManager, AppProfileManager, AppPhotosManager, MtpApiManager, MtpApiFileManager, NotificationsManager, AppMessagesManager, AppPeersManager, ApiUpdatesManager, ContactsSelectService, ErrorService) { $scope.chatFull = AppChatsManager.wrapForFull($scope.chatID, {}); $scope.settings = {notifications: true}; @@ -3485,20 +3510,20 @@ angular.module('myApp.controllers', ['myApp.i18n']) $scope.leaveGroup = function () { - MtpApiManager.invokeApi('messages.deleteChatUser', { - chat_id: AppChatsManager.getChatInput($scope.chatID), - user_id: {_: 'inputUserSelf'} - }).then(onChatUpdated); - }; - - $scope.returnToGroup = function () { - MtpApiManager.invokeApi('messages.addChatUser', { - chat_id: AppChatsManager.getChatInput($scope.chatID), - user_id: {_: 'inputUserSelf'} - }).then(onChatUpdated); + ErrorService.confirm({type: 'HISTORY_LEAVE_AND_FLUSH'}).then(function () { + MtpApiManager.invokeApi('messages.deleteChatUser', { + chat_id: AppChatsManager.getChatInput($scope.chatID), + user_id: {_: 'inputUserSelf'} + }).then(function (updates) { + ApiUpdatesManager.processUpdateMessage(updates); + AppMessagesManager.flushHistory(-$scope.chatID).then(function () { + $modalInstance.close(); + $location.url('/im'); + }); + }); + }); }; - $scope.inviteToGroup = function () { var disabled = []; angular.forEach($scope.chatFull.participants.participants, function(participant){ @@ -3537,10 +3562,15 @@ angular.module('myApp.controllers', ['myApp.i18n']) - $scope.flushHistory = function () { - ErrorService.confirm({type: 'HISTORY_FLUSH'}).then(function () { - AppMessagesManager.flushHistory(-$scope.chatID).then(function () { - $rootScope.$broadcast('history_focus', {peerString: $scope.chatFull.peerString}); + $scope.flushHistory = function (justClear) { + ErrorService.confirm({type: justClear ? 'HISTORY_FLUSH' : 'HISTORY_FLUSH_AND_DELETE'}).then(function () { + AppMessagesManager.flushHistory(-$scope.chatID, justClear).then(function () { + if (justClear) { + $rootScope.$broadcast('history_focus', {peerString: $scope.chatFull.peerString}); + } else { + $modalInstance.close(); + $location.url('/im'); + } }); }); }; diff --git a/app/js/locales/en-us.json b/app/js/locales/en-us.json index 218b3f3b..3cf04770 100644 --- a/app/js/locales/en-us.json +++ b/app/js/locales/en-us.json @@ -20,7 +20,9 @@ "group_modal_menu_delete_photo": "Delete photo", "group_modal_menu_edit_group": "Edit group", "group_modal_menu_leave": "Leave", - "group_modal_menu_delete_chat": "Delete chat", + "group_modal_menu_delete_group": "Delete and exit", + "group_modal_menu_clear_history": "Clear history", + "group_modal_delete_group": "Delete group", "group_modal_settings": "Settings", "group_modal_notifications": "Notifications", "group_modal_menu_share_link": "Invite to group via link", @@ -33,7 +35,6 @@ "group_modal_migrate_item2": "New members see the entire chat history", "group_modal_migrate_item3": "Admins delete messages for everyone", "group_modal_migrate_item4": "Notifications are muted by default", - "group_modal_delete_group": "Delete group", "channel_modal_info": "Channel info", "channel_modal_description": "Description", @@ -132,7 +133,8 @@ "user_modal_share_contact": "Share contact", "user_modal_block_user": "Block user", "user_modal_unblock_user": "Unblock user", - "user_modal_delete_chat": "Delete chat", + "user_modal_clear_history": "Clear history", + "user_modal_delete_chat": "Delete conversation", "user_modal_add_to_group": "Add to group", "user_modal_info": "Info", "user_modal_phone": "Phone", @@ -213,6 +215,7 @@ "confirm_modal_logout": "Are you sure you want to log out?", "confirm_modal_update_reload": "A new version of Telegram Web has been downloaded. Launch it?", "confirm_modal_history_flush": "Are you sure? This can not be undone!", + "confirm_modal_history_leave_flush_md": "Are you sure, you want to delete all message history and leave the group?\n\nThis action cannot be undone.", "confirm_modal_terminate_sessions": "Are you sure you want to log out all devices except for this one?", "confirm_modal_terminate_session": "Are you sure you want to log out this device?", "confirm_modal_clipboard_file_send": "Are you sure to send file(s) from clipboard?", @@ -249,7 +252,9 @@ "confirm_modal_are_u_sure": "Are you sure?", "confirm_modal_logout_submit": "Log out", - "confirm_modal_history_flush_submit": "Delete chat", + "confirm_modal_clear_history_submit": "Clear history", + "confirm_modal_leave_chat_submit": "Leave", + "confirm_modal_delete_chat_submit": "Delete chat", "confirm_modal_clipboard_files_send_submit": "Send", "confirm_modal_clipboard_file_send_submit": "Send", "confirm_modal_message_delete_submit": "Delete", @@ -289,7 +294,6 @@ "contact_import_modal_submit": "Save", "contact_import_modal_submit_active": "Importing...", - "conversation_message_deleted": "deleted message", "conversation_you": "You", "conversation_draft": "Draft:", "conversation_media_photo": "Photo", @@ -419,7 +423,7 @@ "head_media_documents": "Files", "head_media_audio": "Voice messages", "head_about": "About", - "head_clear_all": "Clear all", + "head_clear_all": "Clear history", "head_edit": "Edit", "head_typing": "typing", "head_pluralize_participants": "{'0': 'No members', 'one': '1 member', 'other': '{} members'}", diff --git a/app/js/messages_manager.js b/app/js/messages_manager.js index a0a8a5f9..04841434 100644 --- a/app/js/messages_manager.js +++ b/app/js/messages_manager.js @@ -175,7 +175,8 @@ angular.module('myApp.services') message.pFlags.unread = true; } - if (historiesStorage[peerID] === undefined) { + if (historiesStorage[peerID] === undefined && + !message.deleted) { var historyStorage = {count: null, history: [mid], pending: []}; historiesStorage[peerID] = historyStorage; if (mergeReplyKeyboard(historyStorage, message)) { @@ -308,10 +309,18 @@ angular.module('myApp.services') ApiUpdatesManager.addChannelState(-peerID, historyResult.pts); } + var length = historyResult.messages.length; + if (length && + historyResult.messages[length - 1].deleted) { + historyResult.messages.splice(length - 1, 1); + length--; + historyResult.count--; + } + if ( peerID < 0 || !AppUsersManager.isBot(peerID) || - (historyResult.messages.length == limit && limit < historyResult.count) + (length == limit && limit < historyResult.count) ) { return historyResult; } @@ -364,7 +373,7 @@ angular.module('myApp.services') function fillHistoryStorage (peerID, maxID, fullLimit, historyStorage) { // console.log('fill history storage', peerID, maxID, fullLimit, angular.copy(historyStorage)); var offset = (migratedFromTo[peerID] && !maxID) ? 1 : 0; - return requestHistory (peerID, maxID, fullLimit, offset).then(function (historyResult) { + return requestHistory(peerID, maxID, fullLimit, offset).then(function (historyResult) { historyStorage.count = historyResult.count || historyResult.messages.length; var offset = 0; @@ -1039,8 +1048,13 @@ angular.module('myApp.services') }); } - function doFlushHistory (inputPeer) { + function doFlushHistory (inputPeer, justClear) { + var flags = 0; + if (justClear) { + flags |= 1; + } return MtpApiManager.invokeApi('messages.deleteHistory', { + flags: flags, peer: inputPeer, max_id: 0 }).then(function (affectedHistory) { @@ -1055,18 +1069,22 @@ angular.module('myApp.services') if (!affectedHistory.offset) { return true; } - return doFlushHistory(inputPeer); + return doFlushHistory(inputPeer, justClear); }); } - function flushHistory (peerID) { - return doFlushHistory(AppPeersManager.getInputPeerByID(peerID)).then(function () { - var foundDialog = getDialogByPeerID(peerID); - if (foundDialog[0]) { - dialogsStorage.dialogs.splice(foundDialog[1], 1); + function flushHistory (peerID, justClear) { + return doFlushHistory(AppPeersManager.getInputPeerByID(peerID), justClear).then(function () { + if (justClear) { + $rootScope.$broadcast('dialog_flush', {peerID: peerID}); + } else { + var foundDialog = getDialogByPeerID(peerID); + if (foundDialog[0]) { + dialogsStorage.dialogs.splice(foundDialog[1], 1); + } + delete historiesStorage[peerID]; + $rootScope.$broadcast('dialog_drop', {peerID: peerID}); } - delete historiesStorage[peerID]; - $rootScope.$broadcast('dialog_flush', {peerID: peerID}); }); } @@ -1120,7 +1138,8 @@ angular.module('myApp.services') apiMessage.toID = toPeerID; apiMessage.fromID = apiMessage.pFlags.post ? toPeerID : apiMessage.from_id; - apiMessage.signID = apiMessage.pFlags.post && apiMessage.from_id || fwdHeader && fwdHeader.from_id; + apiMessage.signID = apiMessage.pFlags.post && apiMessage.from_id || + fwdHeader && fwdHeader.channel_id && fwdHeader.from_id; if (apiMessage.via_bot_id > 0) { apiMessage.viaBotID = apiMessage.via_bot_id; @@ -1200,6 +1219,13 @@ angular.module('myApp.services') migrateFrom = -channelID; migrateTo = -apiMessage.action.channel_id; break; + + case 'messageActionHistoryClear': + apiMessage.deleted = true; + apiMessage.clear_history = true; + apiMessage.pFlags.out = false; + apiMessage.pFlags.unread = false; + break; } if (migrateFrom && migrateTo && @@ -2232,6 +2258,11 @@ angular.module('myApp.services') } for (i = start; i < end; i++) { + if (history[i].deleted) { + history.splice(i, 1); + end--; + continue; + } curMessage = history[i]; curDay = Math.floor((curMessage.date + ServerTimeManager.midnightOffset) / 86400); @@ -2731,11 +2762,22 @@ angular.module('myApp.services') safeReplaceObject(wasForHistory, newForHistory); messagesForHistory[mid] = wasForHistory; } - $rootScope.$broadcast('message_edit', { - peerID: peerID, - id: message.id, - mid: mid - }); + + if (message.clear_history) { + var foundDialog = getDialogByPeerID(peerID); + if (foundDialog[0] && + foundDialog[0].top_message == mid) { + $rootScope.$broadcast('dialog_flush', {peerID: peerID}); + } else { + $rootScope.$broadcast('history_delete', {peerID: peerID, msgs: [mid]}); + } + } else { + $rootScope.$broadcast('message_edit', { + peerID: peerID, + id: message.id, + mid: mid + }); + } break; case 'updateReadHistoryInbox': @@ -2875,15 +2917,6 @@ angular.module('myApp.services') } angular.forEach(historiesUpdated, function (updatedData, peerID) { - var foundDialog = getDialogByPeerID(peerID); - if (foundDialog[0]) { - if (updatedData.unread) { - foundDialog[0].unread_count -= updatedData.unread; - - $rootScope.$broadcast('dialog_unread', {peerID: peerID, count: foundDialog[0].unread_count}); - } - } - var historyStorage = historiesStorage[peerID]; if (historyStorage !== undefined) { var newHistory = [], @@ -2912,6 +2945,22 @@ angular.module('myApp.services') $rootScope.$broadcast('history_delete', {peerID: peerID, msgs: updatedData.msgs}); } + + var foundDialog = getDialogByPeerID(peerID)[0]; + if (foundDialog) { + if (updatedData.unread) { + foundDialog.unread_count -= updatedData.unread; + + $rootScope.$broadcast('dialog_unread', { + peerID: peerID, + count: foundDialog.unread_count + }); + } + + if (updatedData.msgs[foundDialog.top_message]) { + reloadConversation(peerID); + } + } }); break; @@ -2999,11 +3048,28 @@ angular.module('myApp.services') saveMessages(dialogsResult.messages); var updatedDialogs = {}; + var hasUpdated = false; angular.forEach(dialogsResult.dialogs, function (dialog) { - saveConversation(dialog); - updatedDialogs[dialog.peerID] = dialog; + if (dialog.top_message) { + saveConversation(dialog); + if (getDialogByPeerID(dialog.peerID).length) { + $rootScope.$broadcast('dialog_top', dialog); + } else { + updatedDialogs[dialog.peerID] = dialog; + hasUpdated = true; + } + } else { + var peerID = AppPeersManager.getPeerID(dialog.peer); + var foundDialog = getDialogByPeerID(peerID); + if (foundDialog.length) { + dialogsStorage.dialogs.splice(foundDialog[1], 1); + $rootScope.$broadcast('dialog_drop', {peerID: peerID}); + } + } }); - $rootScope.$broadcast('dialogs_multiupdate', updatedDialogs); + if (hasUpdated) { + $rootScope.$broadcast('dialogs_multiupdate', updatedDialogs); + } }); } diff --git a/app/partials/desktop/chat_modal.html b/app/partials/desktop/chat_modal.html index f4547fe9..2ba39384 100644 --- a/app/partials/desktop/chat_modal.html +++ b/app/partials/desktop/chat_modal.html @@ -40,13 +40,11 @@