public IObservable <Message> LoadMessages( Aggregate feed, AggregateLoadingState state) { return(LoadAggregateMessages(feed, state) .SelectMany(MapToMessage)); }
private IObservable <TdApi.Message> LoadAggregateMessages( Aggregate aggregate, AggregateLoadingState state) { var actualLimit = _limit; var list = aggregate.Chats.Select(f => { var stackedCount = state.CountStackedMessages(f.ChatData.Id); return(Enumerable.Range(0, stackedCount) .Select(_ => state.PopMessageFromStack(f.ChatData.Id)) // get stacked messages for this chat .ToObservable() .Concat(stackedCount < _limit ? LoadChannelMessages(f, new ChatLoadingState // load messages from the server { LastMessageId = state.GetLastMessageId(f.ChatData.Id) }, _limit, 0) : Observable.Empty <TdApi.Message>()) .Aggregate(new List <TdApi.Message>(), (l, m) => { l.Add(m); return l; }) .Do(l => { // api has no guarantees about actual number of messages returned // actual limit would be equal to min number of messages for all feeds // unless it is zero if (l.Count > 0 && l.Count < actualLimit) { actualLimit = l.Count; } }) .SelectMany(messages => messages)); }); return(list.Merge() .Aggregate(new List <TdApi.Message>(), (l, m) => { l.Add(m); return l; }) .SelectMany(l => { // make sure all messages are unique var all = l.GroupBy(m => m.Id) .Select(g => g.First()) .OrderByDescending(m => m.Date) .ToArray(); var toBeReturned = all.Take(actualLimit); var toBeStacked = all.Skip(actualLimit); // remember last message id foreach (var message in all.Reverse()) { state.SetLastMessageId(message.ChatId, message.Id); } // put into stack foreach (var message in toBeStacked.Reverse()) { state.PushMessageToStack(message.ChatId, message); } return toBeReturned; })); }