Browse Source

Improved channel updates handling

master
Igor Zhukov 9 years ago
parent
commit
923250bc41
  1. 19
      app/js/controllers.js
  2. 162
      app/js/messages_manager.js
  3. 263
      app/js/services.js

19
app/js/controllers.js

@ -654,16 +654,16 @@ angular.module('myApp.controllers', ['myApp.i18n'])
return false; return false;
} }
var topMessages = []; var indexes = [];
var topToDialogs = {}; var indexesToDialogs = {};
angular.forEach(dialogsUpdated, function (dialog, peerID) { angular.forEach(dialogsUpdated, function (dialog, peerID) {
if ($scope.noUsers && peerID > 0) { if ($scope.noUsers && peerID > 0) {
return; return;
} }
topToDialogs[dialog.top_message] = dialog; indexesToDialogs[dialog.index] = dialog;
topMessages.push(dialog.top_message); indexes.push(dialog.index);
}); });
topMessages.sort(); indexes.sort();
var i, dialog; var i, dialog;
var len = $scope.dialogs.length; var len = $scope.dialogs.length;
@ -675,9 +675,9 @@ angular.module('myApp.controllers', ['myApp.i18n'])
len--; len--;
} }
} }
len = topMessages.length; len = indexes.length;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
dialog = topToDialogs[topMessages[i]]; dialog = indexesToDialogs[indexes[i]];
$scope.dialogs.unshift( $scope.dialogs.unshift(
AppMessagesManager.wrapForDialog(dialog.top_message, dialog.unread_count) AppMessagesManager.wrapForDialog(dialog.top_message, dialog.unread_count)
); );
@ -1654,6 +1654,11 @@ angular.module('myApp.controllers', ['myApp.i18n'])
}); });
}); });
$scope.$on('history_reload', function (e, updPeerID) {
if (updPeerID == $scope.curDialog.peerID) {
loadHistory();
}
});
var typingTimeouts = {}; var typingTimeouts = {};
$scope.$on('history_append', function (e, addedMessage) { $scope.$on('history_append', function (e, addedMessage) {

162
app/js/messages_manager.js

@ -140,6 +140,42 @@ angular.module('myApp.services')
return []; return [];
} }
function saveChannelDialog (channelID, dialog) {
var peerID = -channelID;
var peerText = AppPeersManager.getPeerSearchText(peerID);
SearchIndexManager.indexObject(peerID, peerText, dialogsIndex);
var mid = getFullMessageID(dialog.top_important_message, channelID);
dialog.top_message = mid;
dialog.unread_count = dialog.unread_important_count;
dialog.read_inbox_max_id = getFullMessageID(dialog.read_inbox_max_id, channelID);
var message = getMessage(dialog.top_message);
var topDate = message.date;
var channel = AppChatsManager.getChat(channelID);
if (!topDate || channel.date && channel.date > topDate) {
topDate = channel.date;
}
dialog.index = generateDialogIndex(topDate);
dialog.peerID = peerID;
pushDialogToStorage(dialog);
// Because we saved message without dialog present
if (message.mid && message.mid > dialog.read_inbox_max_id) {
message.unread = true;
}
if (historiesStorage[peerID] === undefined) {
var historyStorage = {count: null, history: [mid], pending: []};
historiesStorage[peerID] = historyStorage;
}
NotificationsManager.savePeerSettings(peerID, dialog.notify_settings);
ApiUpdatesManager.addChannelState(channelID, dialog.pts);
}
function getAllChannels () { function getAllChannels () {
if (channelsLoadPromise) { if (channelsLoadPromise) {
return channelsLoadPromise; return channelsLoadPromise;
@ -154,30 +190,10 @@ angular.module('myApp.services')
angular.forEach(dialogsResult.dialogs, function (dialog) { angular.forEach(dialogsResult.dialogs, function (dialog) {
var peerID = AppPeersManager.getPeerID(dialog.peer); var peerID = AppPeersManager.getPeerID(dialog.peer);
var peerText = AppPeersManager.getPeerSearchText(peerID); var channelID = -peerID;
SearchIndexManager.indexObject(peerID, peerText, dialogsIndex); saveChannelDialog(channelID, dialog);
var mid = getFullMessageID(dialog.top_important_message, -peerID);
dialog.top_message = mid;
var message = getMessage(dialog.top_message);
var topDate = message.date;
var channel = AppChatsManager.getChat(-peerID);
if (!topDate || channel.date && channel.date > topDate) {
topDate = channel.date;
}
dialog.index = generateDialogIndex(topDate);
dialog.peerID = peerID;
pushDialogToStorage(dialog);
if (historiesStorage[peerID] === undefined) {
var historyStorage = {count: null, history: [mid], pending: []};
historiesStorage[peerID] = historyStorage;
}
NotificationsManager.savePeerSettings(peerID, dialog.notify_settings); NotificationsManager.savePeerSettings(peerID, dialog.notify_settings);
ApiUpdatesManager.addChannelState(channelID, dialog.pts);
}); });
allChannelsLoaded = true; allChannelsLoaded = true;
}); });
@ -188,7 +204,9 @@ angular.module('myApp.services')
offset: offset, offset: offset,
limit: limit limit: limit
}).then(function (dialogsResult) { }).then(function (dialogsResult) {
TelegramMeWebService.setAuthorized(true); if (!offset) {
TelegramMeWebService.setAuthorized(true);
}
// Server-side bug // Server-side bug
if (dialogsResult.count && offset >= dialogsResult.count) { if (dialogsResult.count && offset >= dialogsResult.count) {
@ -288,8 +306,9 @@ angular.module('myApp.services')
function requestHistory (inputPeer, maxID, limit, offset) { function requestHistory (inputPeer, maxID, limit, offset) {
var peerID = AppPeersManager.getPeerID(inputPeer); var peerID = AppPeersManager.getPeerID(inputPeer);
var isChannel = AppPeersManager.isChannel(peerID);
var promise; var promise;
if (AppPeersManager.isChannel(peerID)) { if (isChannel) {
promise = MtpApiManager.invokeApi('channels.getImportantHistory', { promise = MtpApiManager.invokeApi('channels.getImportantHistory', {
channel: AppChatsManager.getChannelInput(-peerID), channel: AppChatsManager.getChannelInput(-peerID),
offset_id: maxID ? getMessageLocalID(maxID) : 0, offset_id: maxID ? getMessageLocalID(maxID) : 0,
@ -310,6 +329,10 @@ angular.module('myApp.services')
AppChatsManager.saveApiChats(historyResult.chats); AppChatsManager.saveApiChats(historyResult.chats);
saveMessages(historyResult.messages); saveMessages(historyResult.messages);
if (isChannel) {
ApiUpdatesManager.addChannelState(-peerID, historyResult.pts);
}
if ( if (
peerID < 0 || peerID < 0 ||
!AppUsersManager.isBot(peerID) || !AppUsersManager.isBot(peerID) ||
@ -789,7 +812,6 @@ angular.module('myApp.services')
for (i = historyStorage.history.length; i >= 0; i--) { for (i = historyStorage.history.length; i >= 0; i--) {
messageID = historyStorage.history[i]; messageID = historyStorage.history[i];
message = messagesStorage[messageID]; message = messagesStorage[messageID];
// console.log('ms', message);
if (message && !message.out && message.unread) { if (message && !message.out && message.unread) {
foundUnread = true; foundUnread = true;
break; break;
@ -826,6 +848,9 @@ angular.module('myApp.services')
foundDialog[0].unread_count = 0; foundDialog[0].unread_count = 0;
$rootScope.$broadcast('dialog_unread', {peerID: peerID, count: 0}); $rootScope.$broadcast('dialog_unread', {peerID: peerID, count: 0});
$rootScope.$broadcast('messages_read'); $rootScope.$broadcast('messages_read');
if (historyStorage && historyStorage.history.length) {
foundDialog[0].read_inbox_max_id = historyStorage.history[0];
}
} }
})['finally'](function () { })['finally'](function () {
delete historyStorage.readPromise; delete historyStorage.readPromise;
@ -895,7 +920,6 @@ angular.module('myApp.services')
if (apiMessage._ == 'messageEmpty') { if (apiMessage._ == 'messageEmpty') {
return; return;
} }
apiMessage.unread = apiMessage.flags & 1 ? true : false;
apiMessage.out = apiMessage.flags & 2 ? true : false; apiMessage.out = apiMessage.flags & 2 ? true : false;
apiMessage.media_unread = apiMessage.flags & 32 ? true : false; apiMessage.media_unread = apiMessage.flags & 32 ? true : false;
@ -907,6 +931,13 @@ angular.module('myApp.services')
apiMessage.mid = mid; apiMessage.mid = mid;
messagesStorage[mid] = apiMessage; messagesStorage[mid] = apiMessage;
if (channelID && !apiMessage.out) {
var dialog = getDialogByPeerID(toPeerID)[0];
apiMessage.unread = dialog ? mid > dialog.read_inbox_max_id : true;
} else {
apiMessage.unread = apiMessage.flags & 1 ? true : false;
}
if (apiMessage.reply_to_msg_id) { if (apiMessage.reply_to_msg_id) {
apiMessage.reply_to_mid = getFullMessageID(apiMessage.reply_to_msg_id, channelID); apiMessage.reply_to_mid = getFullMessageID(apiMessage.reply_to_msg_id, channelID);
} }
@ -2059,6 +2090,9 @@ angular.module('myApp.services')
function handleNewDialogs () { function handleNewDialogs () {
$timeout.cancel(newDialogsHandlePromise); $timeout.cancel(newDialogsHandlePromise);
newDialogsHandlePromise = false; newDialogsHandlePromise = false;
angular.forEach(newDialogsToHandle, function (dialog) {
pushDialogToStorage(dialog);
});
$rootScope.$broadcast('dialogs_multiupdate', newDialogsToHandle); $rootScope.$broadcast('dialogs_multiupdate', newDialogsToHandle);
newDialogsToHandle = {}; newDialogsToHandle = {};
} }
@ -2089,19 +2123,26 @@ angular.module('myApp.services')
} }
$rootScope.$on('apiUpdate', function (e, update) { $rootScope.$on('apiUpdate', function (e, update) {
// if (update._ != 'updateUserStatus') { if (update._ != 'updateUserStatus') {
// console.log('on apiUpdate', update); console.log('on apiUpdate', update);
// } }
switch (update._) { switch (update._) {
case 'updateMessageID': case 'updateMessageID':
pendingByMessageID[update.id] = update.random_id; pendingByMessageID[update.id] = update.random_id;
break; break;
case 'updateNewMessage': case 'updateNewMessage':
case 'updateNewChannelMessage':
var message = update.message, var message = update.message,
peerID = getMessagePeer(message), peerID = getMessagePeer(message),
historyStorage = historiesStorage[peerID]; historyStorage = historiesStorage[peerID];
if (update._ == 'updateNewChannelMessage' &&
!(message.flags & 16 || message.flags & 2 || (message.flags & 256) == 0)) {
// we don't support not important messages yet
break;
}
saveMessages([message]); saveMessages([message]);
if (historyStorage !== undefined) { if (historyStorage !== undefined) {
@ -2127,12 +2168,11 @@ angular.module('myApp.services')
}; };
} }
if (mergeReplyKeyboard(historyStorage, message)) { if (mergeReplyKeyboard(historyStorage, message)) {
$rootScope.$broadcast('history_reply_markup', {peerID: peerID}) $rootScope.$broadcast('history_reply_markup', {peerID: peerID})
} }
if (!message.out) { if (!message.out && message.from_id) {
AppUsersManager.forceUserOnline(message.from_id); AppUsersManager.forceUserOnline(message.from_id);
} }
@ -2162,24 +2202,20 @@ angular.module('myApp.services')
if (foundDialog.length) { if (foundDialog.length) {
dialog = foundDialog[0]; dialog = foundDialog[0];
if (foundDialog[1] > 0) {
dialogsStorage.dialogs.splice(foundDialog[1], 1);
dialogsStorage.dialogs.unshift(dialog);
}
dialog.top_message = message.mid; dialog.top_message = message.mid;
if (inboxUnread) { if (inboxUnread) {
dialog.unread_count++; dialog.unread_count++;
} }
} else { } else {
SearchIndexManager.indexObject(peerID, AppPeersManager.getPeerSearchText(peerID), dialogsIndex); SearchIndexManager.indexObject(peerID, AppPeersManager.getPeerSearchText(peerID), dialogsIndex);
dialog = { dialog = {
peerID: peerID, peerID: peerID,
unread_count: inboxUnread ? 1 : 0, unread_count: inboxUnread ? 1 : 0,
top_message: message.mid top_message: message.mid
}; };
dialogsStorage.dialogs.unshift(dialog);
} }
dialog.index = generateDialogIndex(message.date);
newDialogsToHandle[peerID] = dialog; newDialogsToHandle[peerID] = dialog;
if (!newDialogsHandlePromise) { if (!newDialogsHandlePromise) {
newDialogsHandlePromise = $timeout(handleNewDialogs, 0); newDialogsHandlePromise = $timeout(handleNewDialogs, 0);
@ -2217,9 +2253,11 @@ angular.module('myApp.services')
case 'updateReadHistoryInbox': case 'updateReadHistoryInbox':
case 'updateReadHistoryOutbox': case 'updateReadHistoryOutbox':
var maxID = update.max_id; case 'updateReadChannelInbox':
var isOut = update._ == 'updateReadHistoryOutbox'; var isOut = update._ == 'updateReadHistoryOutbox';
var peerID = AppPeersManager.getPeerID(update.peer); var channelID = update.channel_id;
var maxID = getFullMessageID(update.max_id, channelID);
var peerID = channelID ? -channelID : AppPeersManager.getPeerID(update.peer);
var foundDialog = getDialogByPeerID(peerID); var foundDialog = getDialogByPeerID(peerID);
var history = (historiesStorage[peerID] || {}).history || []; var history = (historiesStorage[peerID] || {}).history || [];
var newUnreadCount = false; var newUnreadCount = false;
@ -2289,12 +2327,14 @@ angular.module('myApp.services')
break; break;
case 'updateDeleteMessages': case 'updateDeleteMessages':
var dialogsUpdated = {}, case 'updateDeleteChannelMessages':
historiesUpdated = {}, var dialogsUpdated = {};
messageID, message, i, peerID, foundDialog, history; var historiesUpdated = {};
var channelID = update.channel_id;
var messageID, message, i, peerID, foundDialog, history;
for (i = 0; i < update.messages.length; i++) { for (i = 0; i < update.messages.length; i++) {
messageID = update.messages[i]; messageID = getFullMessageID(update.messages[i], channelID);
message = messagesStorage[messageID]; message = messagesStorage[messageID];
if (message) { if (message) {
peerID = getMessagePeer(message); peerID = getMessagePeer(message);
@ -2369,6 +2409,40 @@ angular.module('myApp.services')
} }
}); });
break; break;
case 'updateChannelReload':
var channelID = update.channel_id;
var peerID = -channelID;
delete historiesStorage[peerID];
var foundDialog = getDialogByPeerID(peerID);
if (foundDialog[0]) {
dialogsStorage.dialogs.splice(foundDialog[1], 1);
}
var inputPeer = AppPeersManager.getInputPeerByID(peerID);
$q.all([
getHistory(inputPeer, 0),
AppChatsManager.getChannelFull(channelID, true)
]).then(function (results) {
var historyResult = results[0];
var channelResult = results[1];
var dialog = {
_: 'dialogChannel',
peer: AppPeersManager.getOutputPeer(peerID),
top_message: historyResult.history[0],
top_important_message: historyResult.history[0],
read_inbox_max_id: channelResult.read_inbox_max_id,
unread_count: channelResult.unread_count,
unread_important_count: channelResult.unread_important_count
};
saveChannelDialog(channelID, dialog);
var updatedDialogs = {};
updatedDialogs[peerID] = dialog;
$rootScope.$broadcast('dialogs_multiupdate', updatedDialogs);
$rootScope.$broadcast('history_reload', peerID);
});
break;
} }
}); });

263
app/js/services.js

@ -2254,21 +2254,23 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
.service('ApiUpdatesManager', function ($rootScope, MtpNetworkerFactory, AppUsersManager, AppChatsManager, AppPeersManager, MtpApiManager) { .service('ApiUpdatesManager', function ($rootScope, MtpNetworkerFactory, AppUsersManager, AppChatsManager, AppPeersManager, MtpApiManager) {
var curState = {}; var updatesState = {
pendingPtsUpdates: [],
pendingSeqUpdates: {},
syncPending: false,
syncLoading: true
};
var channelStates = {};
var myID = 0; var myID = 0;
MtpApiManager.getUserID().then(function (id) { MtpApiManager.getUserID().then(function (id) {
myID = id; myID = id;
}); });
var syncPending = false;
var syncLoading = true;
var pendingSeqUpdates = {};
var pendingPtsUpdates = [];
function popPendingSeqUpdate () { function popPendingSeqUpdate () {
var nextSeq = curState.seq + 1, var nextSeq = updatesState.seq + 1,
pendingUpdatesData = pendingSeqUpdates[nextSeq]; pendingUpdatesData = updatesState.pendingSeqUpdates[nextSeq];
if (!pendingUpdatesData) { if (!pendingUpdatesData) {
return false; return false;
} }
@ -2277,32 +2279,33 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
for (var i = 0, length = updates.length; i < length; i++) { for (var i = 0, length = updates.length; i < length; i++) {
saveUpdate(updates[i]); saveUpdate(updates[i]);
} }
curState.seq = pendingUpdatesData.seq; updatesState.seq = pendingUpdatesData.seq;
if (pendingUpdatesData.date && curState.date < pendingUpdatesData.date) { if (pendingUpdatesData.date && updatesState.date < pendingUpdatesData.date) {
curState.date = pendingUpdatesData.date; updatesState.date = pendingUpdatesData.date;
} }
delete pendingSeqUpdates[nextSeq]; delete updatesState.pendingSeqUpdates[nextSeq];
if (!popPendingSeqUpdate() && if (!popPendingSeqUpdate() &&
syncPending && updatesState.syncPending &&
syncPending.seqAwaiting && updatesState.syncPending.seqAwaiting &&
curState.seq >= syncPending.seqAwaiting) { updatesState.seq >= updatesState.syncPending.seqAwaiting) {
if (!syncPending.ptsAwaiting) { if (!updatesState.syncPending.ptsAwaiting) {
clearTimeout(syncPending.timeout); clearTimeout(updatesState.syncPending.timeout);
syncPending = false; updatesState.syncPending = false;
} else { } else {
delete syncPending.seqAwaiting; delete updatesState.syncPending.seqAwaiting;
} }
} }
return true; return true;
} }
function popPendingPtsUpdate () { function popPendingPtsUpdate (channelID) {
if (!pendingPtsUpdates.length) { var curState = channelID ? getChannelState(channelID) : updatesState;
if (!curState.pendingPtsUpdates.length) {
return false; return false;
} }
pendingPtsUpdates.sort(function (a, b) { curState.pendingPtsUpdates.sort(function (a, b) {
return a.pts - b.pts; return a.pts - b.pts;
}); });
@ -2310,8 +2313,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var goodPts = false; var goodPts = false;
var goodIndex = false; var goodIndex = false;
var update; var update;
for (var i = 0, length = pendingPtsUpdates.length; i < length; i++) { for (var i = 0, length = curState.pendingPtsUpdates.length; i < length; i++) {
update = pendingPtsUpdates[i]; update = curState.pendingPtsUpdates[i];
curPts += update.pts_count; curPts += update.pts_count;
if (curPts >= update.pts) { if (curPts >= update.pts) {
goodPts = update.pts; goodPts = update.pts;
@ -2325,17 +2328,17 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
curState.pts = goodPts; curState.pts = goodPts;
for (i = 0; i <= goodIndex; i++) { for (i = 0; i <= goodIndex; i++) {
update = pendingPtsUpdates[i]; update = curState.pendingPtsUpdates[i];
saveUpdate(update); saveUpdate(update);
} }
pendingPtsUpdates.splice(goodIndex, length - goodIndex); curState.pendingPtsUpdates.splice(0, goodIndex + 1);
if (!pendingPtsUpdates.length && syncPending) { if (!curState.pendingPtsUpdates.length && curState.syncPending) {
if (!syncPending.seqAwaiting) { if (!curState.syncPending.seqAwaiting) {
clearTimeout(syncPending.timeout); clearTimeout(curState.syncPending.timeout);
syncPending = false; curState.syncPending = false;
} else { } else {
delete syncPending.ptsAwaiting; delete curState.syncPending.ptsAwaiting;
} }
} }
@ -2343,7 +2346,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} }
function forceGetDifference () { function forceGetDifference () {
if (!syncLoading) { if (!updatesState.syncLoading) {
getDifference(); getDifference();
} }
} }
@ -2409,23 +2412,23 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} }
function getDifference () { function getDifference () {
if (!syncLoading) { if (!updatesState.syncLoading) {
syncLoading = true; updatesState.syncLoading = true;
pendingSeqUpdates = {}; updatesState.pendingSeqUpdates = {};
pendingPtsUpdates = []; updatesState.pendingPtsUpdates = [];
} }
if (syncPending) { if (updatesState.syncPending) {
clearTimeout(syncPending.timeout); clearTimeout(updatesState.syncPending.timeout);
syncPending = false; updatesState.syncPending = false;
} }
MtpApiManager.invokeApi('updates.getDifference', {pts: curState.pts, date: curState.date, qts: -1}).then(function (differenceResult) { MtpApiManager.invokeApi('updates.getDifference', {pts: updatesState.pts, date: updatesState.date, qts: -1}).then(function (differenceResult) {
if (differenceResult._ == 'updates.differenceEmpty') { if (differenceResult._ == 'updates.differenceEmpty') {
console.log(dT(), 'apply empty diff', differenceResult.seq); console.log(dT(), 'apply empty diff', differenceResult.seq);
curState.date = differenceResult.date; updatesState.date = differenceResult.date;
curState.seq = differenceResult.seq; updatesState.seq = differenceResult.seq;
syncLoading = false; updatesState.syncLoading = false;
$rootScope.$broadcast('stateSynchronized'); $rootScope.$broadcast('stateSynchronized');
return false; return false;
} }
@ -2435,7 +2438,15 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
// Should be first because of updateMessageID // Should be first because of updateMessageID
// console.log(dT(), 'applying', differenceResult.other_updates.length, 'other updates'); // console.log(dT(), 'applying', differenceResult.other_updates.length, 'other updates');
angular.forEach(differenceResult.other_updates, function(update){ angular.forEach(differenceResult.other_updates, function(update) {
if (update._ == 'updateChannelTooLong') {
var channelID = update.channel_id;
var channelState = channelStates[channelID];
if (channelState !== undefined && !channelState.syncLoading) {
getChannelDifference(channelID);
}
return;
}
saveUpdate(update); saveUpdate(update);
}); });
@ -2444,32 +2455,129 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
saveUpdate({ saveUpdate({
_: 'updateNewMessage', _: 'updateNewMessage',
message: apiMessage, message: apiMessage,
pts: curState.pts, pts: updatesState.pts,
pts_count: 0 pts_count: 0
}); });
}); });
var nextState = differenceResult.intermediate_state || differenceResult.state; var nextState = differenceResult.intermediate_state || differenceResult.state;
curState.seq = nextState.seq; updatesState.seq = nextState.seq;
curState.pts = nextState.pts; updatesState.pts = nextState.pts;
curState.date = nextState.date; updatesState.date = nextState.date;
console.log(dT(), 'apply diff', curState.seq, curState.pts); console.log(dT(), 'apply diff', updatesState.seq, updatesState.pts);
if (differenceResult._ == 'updates.differenceSlice') { if (differenceResult._ == 'updates.differenceSlice') {
getDifference(); getDifference();
} else { } else {
// console.log(dT(), 'finished get diff'); // console.log(dT(), 'finished get diff');
$rootScope.$broadcast('stateSynchronized'); $rootScope.$broadcast('stateSynchronized');
syncLoading = false; updatesState.syncLoading = false;
} }
}); });
} }
function getChannelDifference (channelID) {
var channelState = getChannelState(channelID);
if (!channelState.syncLoading) {
channelState.syncLoading = true;
channelState.pendingPtsUpdates = [];
}
MtpApiManager.invokeApi('updates.getChannelDifference', {
channel: AppChatsManager.getChannelInput(channelID),
filter: {_: 'channelMessagesFilterEmpty'},
pts: channelState.pts,
limit: 10
}).then(function (differenceResult) {
channelState.pts = differenceResult.pts;
if (differenceResult._ == 'updates.channelDifferenceEmpty') {
console.log(dT(), 'apply channel empty diff', differenceResult);
channelState.syncLoading = false;
$rootScope.$broadcast('stateSynchronized');
return false;
}
if (differenceResult._ == 'updates.channelDifferenceTooLong') {
console.log(dT(), 'channel diff too long', differenceResult);
channelState.syncLoading = false;
delete channelStates[channelID];
saveUpdate({_: 'updateChannelReload', channel_id: channelID});
return false;
}
AppUsersManager.saveApiUsers(differenceResult.users);
AppChatsManager.saveApiChats(differenceResult.chats);
// Should be first because of updateMessageID
console.log(dT(), 'applying', differenceResult.other_updates.length, 'channel other updates');
angular.forEach(differenceResult.other_updates, function(update){
saveUpdate(update);
});
console.log(dT(), 'applying', differenceResult.new_messages.length, 'channel new messages');
angular.forEach(differenceResult.new_messages, function (apiMessage) {
saveUpdate({
_: 'updateNewChannelMessage',
message: apiMessage,
pts: channelState.pts,
pts_count: 0
});
});
console.log(dT(), 'apply channel diff', channelState.pts);
if (differenceResult._ == 'updates.channelDifference' && !(differenceResult.flags & 1)) {
getChannelDifference(channelID);
} else {
console.log(dT(), 'finished channel get diff');
$rootScope.$broadcast('stateSynchronized');
channelState.syncLoading = false;
}
});
}
function addChannelState (channelID, pts) {
if (channelStates[channelID] === undefined) {
channelStates[channelID] = {
pts: pts,
pendingPtsUpdates: [],
syncPending: false,
syncLoading: false
};
return true;
}
return false;
}
function getChannelState (channelID, pts) {
if (channelStates[channelID] === undefined) {
if (!pts) {
throw new Error('Get channel empty state without pts ' + channelID);
}
addChannelState(channelID, pts);
}
return channelStates[channelID];
}
function processUpdate (update, options) { function processUpdate (update, options) {
if (syncLoading) { var channelID = false;
switch (update._) {
case 'updateNewChannelMessage':
channelID = -AppPeersManager.getPeerID(update.message.to_id);
break;
case 'updateDeleteChannelMessages':
channelID = update.channel_id;
break;
}
var curState = channelID ? getChannelState(channelID, update.pts) : updatesState;
console.log('process', channelID, curState, update);
if (curState.syncLoading) {
return false; return false;
} }
if (update._ == 'updateNewMessage') { if (update._ == 'updateNewMessage') {
var message = update.message; var message = update.message;
var fwdPeerID = message.fwd_from_id ? AppPeersManager.getPeerID(message.fwd_from_id) : 0; var fwdPeerID = message.fwd_from_id ? AppPeersManager.getPeerID(message.fwd_from_id) : 0;
@ -2491,15 +2599,19 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var newPts = curState.pts + (update.pts_count || 0); var newPts = curState.pts + (update.pts_count || 0);
if (newPts < update.pts) { if (newPts < update.pts) {
console.log(dT(), 'Pts hole', curState, update); console.log(dT(), 'Pts hole', curState, update);
pendingPtsUpdates.push(update); curState.pendingPtsUpdates.push(update);
if (!syncPending) { if (!curState.syncPending) {
syncPending = { curState.syncPending = {
timeout: setTimeout(function () { timeout: setTimeout(function () {
getDifference(); if (channelID) {
getChannelDifference(channelID);
} else {
getDifference();
}
}, 5000) }, 5000)
}; };
} }
syncPending.ptsAwaiting = true; curState.syncPending.ptsAwaiting = true;
return false; return false;
} }
if (update.pts > curState.pts) { if (update.pts > curState.pts) {
@ -2507,29 +2619,29 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
popPts = true; popPts = true;
} }
} }
else if (options.seq > 0) { else if (!channelID && options.seq > 0) {
var seq = options.seq; var seq = options.seq;
var seqStart = options.seqStart || seq; var seqStart = options.seqStart || seq;
if (seqStart != curState.seq + 1) { if (seqStart != curState.seq + 1) {
if (seqStart > curState.seq) { if (seqStart > curState.seq) {
console.warn(dT(), 'Seq hole', curState, syncPending && syncPending.seqAwaiting); console.warn(dT(), 'Seq hole', curState, curState.syncPending && curState.syncPending.seqAwaiting);
if (pendingSeqUpdates[seqStart] === undefined) { if (curState.pendingSeqUpdates[seqStart] === undefined) {
pendingSeqUpdates[seqStart] = {seq: seq, date: options.date, updates: []}; curState.pendingSeqUpdates[seqStart] = {seq: seq, date: options.date, updates: []};
} }
pendingSeqUpdates[seqStart].updates.push(update); curState.pendingSeqUpdates[seqStart].updates.push(update);
if (!syncPending) { if (!curState.syncPending) {
syncPending = { curState.syncPending = {
timeout: setTimeout(function () { timeout: setTimeout(function () {
getDifference(); getDifference();
}, 5000) }, 5000)
}; };
} }
if (!syncPending.seqAwaiting || if (!curState.syncPending.seqAwaiting ||
syncPending.seqAwaiting < seqStart) { curState.syncPending.seqAwaiting < seqStart) {
syncPending.seqAwaiting = seqStart; curState.syncPending.seqAwaiting = seqStart;
} }
return false; return false;
} }
@ -2544,12 +2656,10 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} }
} }
saveUpdate(update);
saveUpdate (update);
if (popPts) { if (popPts) {
popPendingPtsUpdate(); popPendingPtsUpdate(channelID);
} }
else if (popSeq) { else if (popSeq) {
popPendingSeqUpdate(); popPendingSeqUpdate();
@ -2563,16 +2673,16 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function attach () { function attach () {
MtpNetworkerFactory.setUpdatesProcessor(processUpdateMessage); MtpNetworkerFactory.setUpdatesProcessor(processUpdateMessage);
MtpApiManager.invokeApi('updates.getState', {}, {noErrorBox: true}).then(function (stateResult) { MtpApiManager.invokeApi('updates.getState', {}, {noErrorBox: true}).then(function (stateResult) {
curState.seq = stateResult.seq; updatesState.seq = stateResult.seq;
curState.pts = stateResult.pts; updatesState.pts = stateResult.pts;
curState.date = stateResult.date; updatesState.date = stateResult.date;
setTimeout(function () { setTimeout(function () {
syncLoading = false; updatesState.syncLoading = false;
}, 1000); }, 1000);
// curState.seq = 1; // updatesState.seq = 1;
// curState.pts = stateResult.pts - 5000; // updatesState.pts = stateResult.pts - 5000;
// curState.date = 1; // updatesState.date = 1;
// getDifference(); // getDifference();
}) })
} }
@ -2580,6 +2690,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return { return {
processUpdateMessage: processUpdateMessage, processUpdateMessage: processUpdateMessage,
addChannelState: addChannelState,
attach: attach attach: attach
} }
}) })

Loading…
Cancel
Save