예제 #1
0
 public IObservable <Message> LoadMessages(
     Aggregate feed,
     AggregateLoadingState state)
 {
     return(LoadAggregateMessages(feed, state)
            .SelectMany(MapToMessage));
 }
예제 #2
0
        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;
            }));
        }