Beispiel #1
0
        public static Paragraph Convert(TLMessageService serviceMessage, bool useActiveLinks)
        {
            var fromId       = serviceMessage.FromId;
            var user         = InMemoryCacheService.Current.GetUser(fromId ?? 0);
            var userFullName = user != null ? user.FullName : AppResources.UserNominativeSingular;
            var action       = serviceMessage.Action;

            if (serviceMessage.ToId is TLPeerChannel)
            {
                var channel = InMemoryCacheService.Current.GetChat(serviceMessage.ToId.Id) as TLChannel;

                if (action is TLMessageActionAdminLogEvent eventAction && _actionsCache.TryGetValue(eventAction.Event.Action.GetType(), out Func <TLMessageService, TLChannelAdminLogEventActionBase, int, string, bool, Paragraph> func))
                {
                    return(func.Invoke(serviceMessage, eventAction.Event.Action, fromId.Value, userFullName, useActiveLinks));
                }
            }

            if (action is TLMessageActionDate dateAction)
            {
                return(ReplaceLinks(serviceMessage, DateTimeToFormatConverter.ConvertDayGrouping(Utils.UnixTimestampToDateTime(dateAction.Date))));
            }

            var paragraph = new Paragraph();

            paragraph.Inlines.Add(new Run {
                Text = AppResources.MessageActionEmpty
            });
            return(paragraph);
        }
        private void OnContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
        {
            if (args.InRecycleQueue)
            {
                return;
            }

            var message = args.Item as Message;

            if (args.ItemContainer.ContentTemplateRoot is SimpleHyperlinkButton hyperlink)
            {
                if (message.Content is MessagePhoto photoMessage)
                {
                    var small = photoMessage.Photo.GetSmall();
                    var photo = hyperlink.Content as Image;
                    photo.Source = PlaceholderHelper.GetBitmap(ViewModel.ProtoService, small.Photo, 0, 0);
                }
                else if (message.Content is MessageVideo videoMessage && videoMessage.Video.Thumbnail != null)
                {
                    var grid  = hyperlink.Content as Grid;
                    var photo = grid.Children[0] as Image;
                    photo.Source = PlaceholderHelper.GetBitmap(ViewModel.ProtoService, videoMessage.Video.Thumbnail.Photo, 0, 0);

                    var panel    = grid.Children[1] as Grid;
                    var duration = panel.Children[1] as TextBlock;
                    duration.Text = videoMessage.Video.GetDuration();
                }
            }
            else if (args.ItemContainer.ContentTemplateRoot is SharedFileCell fileCell)
            {
                fileCell.UpdateMessage(ViewModel.ProtoService, ViewModel, message);
            }
            else if (args.ItemContainer.ContentTemplateRoot is SharedLinkCell linkCell)
            {
                linkCell.UpdateMessage(ViewModel.ProtoService, ViewModel.NavigationService, message);
            }
            else if (args.ItemContainer.ContentTemplateRoot is SharedAudioCell audioCell)
            {
                audioCell.UpdateMessage(ViewModel.PlaybackService, ViewModel.ProtoService, message);
            }
            else if (args.ItemContainer.ContentTemplateRoot is SharedVoiceCell voiceCell)
            {
                voiceCell.UpdateMessage(ViewModel.PlaybackService, ViewModel.ProtoService, message);
            }
            else if (message.Content is MessageHeaderDate && args.ItemContainer.ContentTemplateRoot is Border content && content.Child is TextBlock header)
            {
                header.Text = DateTimeToFormatConverter.ConvertMonthGrouping(Utils.UnixTimestampToDateTime(message.Date));
            }

            if (args.ItemContainer.ContentTemplateRoot is FrameworkElement element)
            {
                element.Tag = message;
            }
        }
Beispiel #3
0
 private static (string Text, IList <TextEntity> Entities) UpdateHeaderDate(MessageViewModel message, MessageHeaderDate headerDate, bool active)
 {
     return(DateTimeToFormatConverter.ConvertDayGrouping(Utils.UnixTimestampToDateTime(message.Date)), null);
 }
        private void UpdateHeaderDate()
        {
            if (_panel == null || _panel.FirstVisibleIndex < 0)
            {
                return;
            }

            var minItem = true;
            var minDate = true;

            for (int i = _panel.FirstVisibleIndex; i <= _panel.LastVisibleIndex; i++)
            {
                var container = Messages.ContainerFromIndex(i) as SelectorItem;
                if (container == null)
                {
                    continue;
                }

                var message = Messages.ItemFromContainer(container) as MessageViewModel;
                if (message == null)
                {
                    continue;
                }

                //if (i == _panel.FirstVisibleIndex)
                //{
                //    DateHeaderLabel.Text = DateTimeToFormatConverter.ConvertDayGrouping(Utils.UnixTimestampToDateTime(message.Date));
                //}

                var transform = container.TransformToVisual(DateHeaderRelative);
                var point     = transform.TransformPoint(new Point());
                var height    = (float)DateHeader.ActualHeight;
                var offset    = (float)point.Y + height;

                if (point.Y + container.ActualHeight >= 0 && minItem)
                {
                    minItem = false;
                    DateHeaderLabel.Text = DateTimeToFormatConverter.ConvertDayGrouping(Utils.UnixTimestampToDateTime(message.Date));
                }

                if (message.Content is MessageHeaderDate && minDate)
                {
                    minDate = false;

                    if (offset >= 0 && offset < height)
                    {
                        container.Opacity = 0;
                    }
                    else
                    {
                        container.Opacity = 1;
                    }

                    if (offset >= height && offset < height * 2)
                    {
                        _dateHeader.Offset = new Vector3(0, -height * 2 + offset, 0);
                    }
                    else
                    {
                        _dateHeader.Offset = new Vector3();
                    }
                }
                else
                {
                    container.Opacity = 1;
                }
            }
        }
Beispiel #5
0
        private void UpdateHeaderDate(bool intermediate)
        {
            var panel = Messages.ItemsPanelRoot as ItemsStackPanel;

            if (panel == null || panel.FirstVisibleIndex < 0)
            {
                return;
            }

            var minItem = true;
            var minDate = true;

            for (int i = panel.FirstVisibleIndex; i <= panel.LastVisibleIndex; i++)
            {
                var container = Messages.ContainerFromIndex(i) as SelectorItem;
                if (container == null)
                {
                    continue;
                }

                var message = Messages.ItemFromContainer(container) as MessageViewModel;
                if (message == null)
                {
                    continue;
                }

                if (minItem)
                {
                    var transform = container.TransformToVisual(DateHeaderRelative);
                    var point     = transform.TransformPoint(new Point());

                    if (point.Y + container.ActualHeight >= 0)
                    {
                        minItem = false;

                        if (message.SchedulingState is MessageSchedulingStateSendAtDate sendAtDate)
                        {
                            DateHeaderLabel.Text = string.Format(Strings.Resources.MessageScheduledOn, DateTimeToFormatConverter.ConvertDayGrouping(Utils.UnixTimestampToDateTime(sendAtDate.SendDate)));
                        }
                        else if (message.SchedulingState is MessageSchedulingStateSendWhenOnline)
                        {
                            DateHeaderLabel.Text = Strings.Resources.MessageScheduledUntilOnline;
                        }
                        else
                        {
                            DateHeaderLabel.Text = DateTimeToFormatConverter.ConvertDayGrouping(Utils.UnixTimestampToDateTime(message.Date));
                        }
                    }
                }

                if (message.Content is MessageHeaderDate && minDate)
                {
                    var transform = container.TransformToVisual(DateHeaderRelative);
                    var point     = transform.TransformPoint(new Point());
                    var height    = (float)DateHeader.ActualHeight;
                    var offset    = (float)point.Y + height;

                    minDate = false;

                    if (offset >= 0 && offset < height)
                    {
                        container.Opacity = 0;
                    }
                    else
                    {
                        container.Opacity = 1;
                    }

                    if (offset >= height && offset < height * 2)
                    {
                        _dateHeader.Offset = new Vector3(0, -height * 2 + offset, 0);
                    }
                    else
                    {
                        _dateHeader.Offset = new Vector3();
                    }
                }
                else
                {
                    container.Opacity = 1;
                }
            }

            _dateHeaderTimer.Stop();
            _dateHeaderTimer.Start();
            VisualUtilities.SetIsVisible(DateHeaderPanel, true);
        }
Beispiel #6
0
        private async void OnViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
        {
            if (Messages.ScrollingHost.ScrollableHeight - Messages.ScrollingHost.VerticalOffset < 120)
            {
                if (ViewModel.IsFirstSliceLoaded)
                {
                    ViewModel.UpdatingScrollMode = UpdatingScrollMode.KeepLastItemInView;
                }

                Arrow.Visibility = Visibility.Collapsed;
            }
            else
            {
                Arrow.Visibility = Visibility.Visible;
            }

            //if (ViewModel.Peer is TLInputPeerUser)
            //{
            //    lvDialogs.ScrollingHost.ViewChanged -= OnViewChanged;
            //    return;
            //}

            var index0 = _panel.FirstVisibleIndex;
            var index1 = _panel.LastVisibleIndex;

            var show     = false;
            var date     = DateTime.Now;
            var message0 = default(TLMessageCommonBase);

            if (index0 > -1 && index1 > -1 /*&& (index0 != _lastIndex0 || index1 != _lastIndex1)*/ && !e.IsIntermediate)
            {
                var container0 = Messages.ContainerFromIndex(index0);
                if (container0 != null)
                {
                    var item0 = Messages.ItemFromContainer(container0);
                    if (item0 != null)
                    {
                        message0 = item0 as TLMessageCommonBase;
                        var date0 = BindConvert.Current.DateTime(message0.Date);

                        var service0 = message0 as TLMessageService;
                        if (service0 != null)
                        {
                            show = !(service0.Action is TLMessageActionDate);
                        }
                        else
                        {
                            show = true;
                        }

                        date = date0.Date;
                    }
                }

                var messageIds = new TLVector <int>();
                var dialog     = ViewModel.Dialog;

                for (int i = index0; i <= index1; i++)
                {
                    var container = Messages.ContainerFromIndex(i);
                    if (container != null)
                    {
                        var item = Messages.ItemFromContainer(container);
                        if (item != null && item is TLMessageCommonBase commonMessage && !commonMessage.IsOut)
                        {
                            //if (commonMessage.IsUnread)
                            //{
                            //    Debug.WriteLine($"Messager {commonMessage.Id} is unread.");
                            //    ViewModel.MarkAsRead(commonMessage);
                            //}

                            if (commonMessage.IsMentioned && commonMessage.IsMediaUnread)
                            {
                                commonMessage.IsMediaUnread = false;
                                commonMessage.RaisePropertyChanged(() => commonMessage.IsMediaUnread);

                                if (dialog != null)
                                {
                                    dialog.UnreadMentionsCount = Math.Max(0, dialog.UnreadMentionsCount - 1);
                                    dialog.RaisePropertyChanged(() => dialog.UnreadMentionsCount);
                                }

                                messageIds.Add(commonMessage.Id);
                            }
                        }
                    }
                }

                if (messageIds.Count > 0)
                {
                    if (ViewModel.With is TLChannel channel)
                    {
                        ViewModel.ProtoService.ReadMessageContentsAsync(channel.ToInputChannel(), messageIds, null);
                    }
                    else
                    {
                        ViewModel.ProtoService.ReadMessageContentsAsync(messageIds, null);
                    }
                }

                #region OLD

                //////Cache();
                ////Cache(index0 + 1, index1);

                ////var itemsPerGroup = 0;
                ////var compositor = ElementCompositionPreview.GetElementVisual(lvDialogs);
                ////var props = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(lvDialogs.ScrollingHost);

                ////for (int i = index1; i >= index0; i--)
                ////{
                ////    var container = lvDialogs.ContainerFromIndex(i) as ListViewItem;
                ////    if (container != null)
                ////    {
                ////        var item = container.Content as TLMessage;
                ////        if (item != null && (item.IsFirst || i == index0) && (!item.IsOut || item.IsPost))
                ////        {
                ////            var text = "0";
                ////            if (i == 0)
                ////            {
                ////                _wasFirst[i] = true;
                ////                text = "Max(0, Reference.Y + Scrolling.Translation.Y)"; // Compression effect
                ////                text = "0";
                ////            }
                ////            else if (i == index0 && itemsPerGroup > 0)
                ////            {
                ////                _wasFirst[i] = true;
                ////                text = "0";
                ////            }
                ////            else if (i == index0)
                ////            {
                ////                _wasFirst[i] = true;
                ////                text = "Min(0, Reference.Y + Scrolling.Translation.Y)";
                ////            }
                ////            else
                ////            {
                ////                text = "Reference.Y + Scrolling.Translation.Y";
                ////            }

                ////            var visual = ElementCompositionPreview.GetElementVisual(container);
                ////            var offset = visual.Offset;
                ////            if (offset.Y == 0)
                ////            {
                ////                var transform = container.TransformToVisual(lvDialogs);
                ////                var point = transform.TransformPoint(new Point());
                ////                offset = new Vector3(0, (float)point.Y, 0);
                ////            }

                ////            var expression = visual.Compositor.CreateExpressionAnimation(text);
                ////            expression.SetVector3Parameter("Reference", offset); //visual.Offset);
                ////            expression.SetReferenceParameter("Scrolling", props);

                ////            if (_inUse.ContainsKey(i) && _wasFirst.ContainsKey(i) && i != index0)
                ////            {
                ////                _wasFirst.Remove(i);

                ////                var border = _inUse[i] as Border;
                ////                var ellipse = ElementCompositionPreview.GetElementVisual(border.Child);
                ////                ellipse.StopAnimation("Offset.Y");
                ////                ellipse.StartAnimation("Offset.Y", expression);
                ////            }
                ////            else if (!_inUse.ContainsKey(i))
                ////            {
                ////                var ellipse = Push(i, item.FromId ?? 0, item);
                ////                ellipse.StopAnimation("Offset.Y");
                ////                ellipse.StartAnimation("Offset.Y", expression);
                ////            }

                ////            itemsPerGroup = 0;
                ////        }
                ////        else if (item != null && item.IsOut)
                ////        {

                ////        }
                ////        else
                ////        {
                ////            itemsPerGroup++;
                ////        }
                ////    }
                ////}


                #endregion

                //Update();
            }

            if (show)
            {
                var paragraph = new Paragraph();
                paragraph.Inlines.Add(new Run {
                    Text = DateTimeToFormatConverter.ConvertDayGrouping(date)
                });

                DateHeader.DataContext = message0;
                DateHeader.Visibility  = Visibility.Visible;
                DateHeaderLabel.Blocks.Clear();
                DateHeaderLabel.Blocks.Add(paragraph);
            }
            else
            {
                DateHeader.Visibility = Visibility.Collapsed;
            }

            if (e.IsIntermediate == false)
            {
                await Task.Delay(4000);

                DateHeader.Visibility = Visibility.Collapsed;
            }
        }
Beispiel #7
0
        private void UpdateHeaderDate(bool intermediate)
        {
            var panel = Messages.ItemsPanelRoot as ItemsStackPanel;

            if (panel == null || panel.FirstVisibleIndex < 0)
            {
                return;
            }

            var top    = 0d;
            var bottom = 0d;

            var knockout = SettingsService.Current.Diagnostics.BubbleKnockout;
            var start    = knockout ? panel.FirstCacheIndex : panel.FirstVisibleIndex;
            var end      = knockout ? panel.LastCacheIndex : panel.LastVisibleIndex;

            var minKnock = knockout;
            var minItem  = true;
            var minDate  = true;

            for (int i = start; i <= end; i++)
            {
                var container = Messages.ContainerFromIndex(i) as SelectorItem;
                if (container == null)
                {
                    continue;
                }

                var message = Messages.ItemFromContainer(container) as MessageViewModel;
                if (message == null)
                {
                    continue;
                }

                if (minKnock)
                {
                    var negative = Messages.TransformToVisual(container);
                    var relative = negative.TransformPoint(new Point());

                    top    = relative.Y;
                    bottom = relative.Y + Messages.ActualHeight;

                    minKnock = false;
                }

                if (minItem && i >= panel.FirstVisibleIndex)
                {
                    var transform = container.TransformToVisual(DateHeaderRelative);
                    var point     = transform.TransformPoint(new Point());

                    if (point.Y + container.ActualHeight >= 0)
                    {
                        minItem = false;

                        if (message.SchedulingState is MessageSchedulingStateSendAtDate sendAtDate)
                        {
                            DateHeaderLabel.Text = string.Format(Strings.Resources.MessageScheduledOn, DateTimeToFormatConverter.ConvertDayGrouping(Utils.UnixTimestampToDateTime(sendAtDate.SendDate)));
                        }
                        else if (message.SchedulingState is MessageSchedulingStateSendWhenOnline)
                        {
                            DateHeaderLabel.Text = Strings.Resources.MessageScheduledUntilOnline;
                        }
                        else
                        {
                            DateHeaderLabel.Text = DateTimeToFormatConverter.ConvertDayGrouping(Utils.UnixTimestampToDateTime(message.Date));
                        }
                    }
                }

                if (message.Content is MessageHeaderDate && minDate && i >= panel.FirstVisibleIndex)
                {
                    var transform = container.TransformToVisual(DateHeaderRelative);
                    var point     = transform.TransformPoint(new Point());
                    var height    = (float)DateHeader.ActualHeight;
                    var offset    = (float)point.Y + height;

                    minDate = false;

                    if (offset >= 0 && offset < height)
                    {
                        container.Opacity = 0;
                    }
                    else
                    {
                        container.Opacity = 1;
                    }

                    if (offset >= height && offset < height * 2)
                    {
                        _dateHeader.Offset = new Vector3(0, -height * 2 + offset, 0);
                    }
                    else
                    {
                        _dateHeader.Offset = new Vector3();
                    }
                }
                else
                {
                    container.Opacity = 1;
                }

                if (knockout && container.ContentTemplateRoot is MessageBubble bubble)
                {
                    bubble.UpdateKnockout(top / container.ActualHeight, bottom / container.ActualHeight);
                }

                top    -= container.ActualHeight;
                bottom -= container.ActualHeight;
            }

            _dateHeaderTimer.Stop();
            _dateHeaderTimer.Start();
            VisualUtilities.SetIsVisible(DateHeaderPanel, true);
        }
Beispiel #8
0
        static ServiceHelper()
        {
            _actionsCache = new Dictionary <Type, Func <TLMessageService, TLMessageActionBase, int, string, bool, Paragraph> >();
            _actionsCache.Add(typeof(TLMessageActionDate), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) => ReplaceLinks(message, DateTimeToFormatConverter.ConvertDayGrouping(Utils.UnixTimestampToDateTime(((TLMessageActionDate)action).Date))));
            _actionsCache.Add(typeof(TLMessageActionEmpty), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) => ReplaceLinks(message, AppResources.MessageActionEmpty));
            _actionsCache.Add(typeof(TLMessageActionGameScore), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) =>
            {
                var value          = ((TLMessageActionGameScore)action).Score;
                var won            = value == 0 || value > 0;
                var serviceMessage = message as TLMessageService;
                if (serviceMessage != null)
                {
                    var game = GetGame(serviceMessage);
                    if (game != null)
                    {
                        var text = game.Title.ToString();
                        //TLMessageCommon tLMessageCommon = serviceMessage.Reply as TLMessageCommonBase;
                        //if (tLMessageCommon != null)
                        //{
                        //    text = ServiceMessageToTextConverter.GetGameFullNameString(text, serviceMessage.Index, serviceMessage.ToId, useActiveLinks);
                        //}

                        if (fromUserId == SettingsHelper.UserId)
                        {
                            return(ReplaceLinks(serviceMessage, won ? AppResources.YourScoredAtGamePlural : AppResources.YourScoredAtGame, new[] { value.ToString(), game.Title }, new[] { "tg-bold://", "tg-game://" }, useActiveLinks));
                        }

                        return(ReplaceLinks(serviceMessage, won ? AppResources.UserScoredAtGamePlural : AppResources.UserScoredAtGame, new[] { fromUserFullName, value.ToString(), game.Title }, new[] { "tg-user://" + fromUserId, "tg-bold://", "tg-game://" }, useActiveLinks));
                    }

                    if (fromUserId == SettingsHelper.UserId)
                    {
                        return(ReplaceLinks(serviceMessage, string.Format(won ? AppResources.YourScoredPlural : AppResources.YourScored, value)));
                    }

                    return(ReplaceLinks(serviceMessage, won ? AppResources.UserScoredPlural : AppResources.UserScored, new[] { fromUserFullName, value.ToString() }, new[] { "tg-user://" + fromUserId, "tg-bold://" }, useActiveLinks));
                }

                return(ReplaceLinks(serviceMessage, won ? AppResources.UserScoredPlural : AppResources.UserScored, new[] { AppResources.UserNominativeSingular, value.ToString() }, new[] { "tg-bold://", "tg-bold://" }, useActiveLinks));
            });
            _actionsCache.Add(typeof(TLMessageActionChatCreate), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) => ReplaceLinks(message, AppResources.MessageActionChatCreate, new[] { fromUserFullName, ((TLMessageActionChatCreate)action).Title }, new[] { "tg-user://" + fromUserId }, useActiveLinks));
            _actionsCache.Add(typeof(TLMessageActionChatEditPhoto), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) => ReplaceLinks(message, AppResources.MessageActionChatEditPhoto, new[] { fromUserFullName }, new[] { "tg-user://" + fromUserId }, useActiveLinks));
            _actionsCache.Add(typeof(TLMessageActionChatEditTitle), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) => ReplaceLinks(message, AppResources.MessageActionChatEditTitle, new[] { fromUserFullName, ((TLMessageActionChatEditTitle)action).Title }, new[] { "tg-user://" + fromUserId }, useActiveLinks));
            _actionsCache.Add(typeof(TLMessageActionChatDeletePhoto), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) => ReplaceLinks(message, AppResources.MessageActionChatDeletePhoto, new[] { fromUserFullName }, new[] { "tg-user://" + fromUserId }, useActiveLinks));
            _actionsCache.Add(typeof(TLMessageActionChatAddUser), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) =>
            {
                var users = ((TLMessageActionChatAddUser)action).Users;
                var names = new List <string>();
                var codes = new List <string>();

                for (int i = 0; i < users.Count; i++)
                {
                    var item = users[i];
                    var user = InMemoryCacheService.Current.GetUser(item);
                    if (user != null)
                    {
                        names.Add(user.FullName);
                        codes.Add($"{{{i + 1}}}");
                    }
                }

                if (users.Count == 1 && users[0] == fromUserId)
                {
                    return(ReplaceLinks(message, AppResources.MessageActionChatAddSelf, new[] { names[0] }, new[] { "tg-user://" + users[0] }, useActiveLinks));
                }

                // TODO: replace last ", " with "and "

                var codesReplace = "{1}";
                if (codes.Count > 1)
                {
                    codesReplace = string.Concat(string.Join(", ", codes.Take(codes.Count - 1)), " and ", codes.Last());
                }

                var tags = users.Select(x => "tg-user://" + x).ToList();
                names.Insert(0, fromUserFullName);
                tags.Insert(0, "tg-user://" + fromUserId);

                return(ReplaceLinks(message, string.Format(AppResources.MessageActionChatAddUser, "{0}", codesReplace), names.ToArray(), tags.ToArray(), useActiveLinks));
            });
            _actionsCache.Add(typeof(TLMessageActionChatDeleteUser), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) =>
            {
                var userId       = ((TLMessageActionChatDeleteUser)action).UserId;
                var user         = InMemoryCacheService.Current.GetUser(userId);
                var userFullName = user.FullName;
                if (userId != fromUserId)
                {
                    return(ReplaceLinks(message, AppResources.MessageActionChatDeleteUser, new[] { fromUserFullName, userFullName }, new[] { "tg-user://" + fromUserId, "tg-user://" + userId }, useActiveLinks));
                }

                if (fromUserId == SettingsHelper.UserId)
                {
                    return(ReplaceLinks(message, AppResources.MessageActionLeftGroupSelf));
                }

                return(ReplaceLinks(message, AppResources.MessageActionUserLeftGroup, new[] { fromUserFullName }, new[] { "tg-user://" + fromUserId }, useActiveLinks));
            });
            _actionsCache.Add(typeof(TLMessageActionScreenshotTaken), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) =>
            {
                if (fromUserId == SettingsHelper.UserId)
                {
                    return(ReplaceLinks(message, AppResources.MessageActionYouScreenshotMessages));
                }

                return(ReplaceLinks(message, AppResources.MessageActionScreenshotMessages, new[] { fromUserFullName }, new[] { "tg-user://" + fromUserId }, useActiveLinks));
            });
            //_actionsCache.Add(typeof(TLMessageActionUnreadMessages), (TLMessageBase message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) => AppResources.UnreadMessages.ToLowerInvariant());
            //_actionsCache.Add(typeof(TLMessageActionContactRegistered), delegate (TLMessageBase message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks)
            //{
            //    TLInt userId = ((TLMessageActionContactRegistered)action).UserId;
            //    TLUserBase user = IoC.Get<ICacheService>(null).GetUser(userId);
            //    string text = (user != null) ? user.FirstName.ToString() : AppResources.User;
            //    if (string.IsNullOrEmpty(text) && user != null)
            //    {
            //        text = user.FullName;
            //    }
            //    return string.Format(AppResources.ContactRegistered, text);
            //});
            _actionsCache.Add(typeof(TLMessageActionChatJoinedByLink), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) => ReplaceLinks(message, AppResources.MessageActionChatJoinedByLink, new[] { fromUserFullName }, new[] { "tg-user://" + fromUserId }, useActiveLinks));
            //_actionsCache.Add(typeof(TLMessageActionMessageGroup), delegate (TLMessageBase message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks)
            //{
            //    int value = ((TLMessageActionMessageGroup)action).Group.Count.Value;
            //    return Language.Declension(value, AppResources.CommentNominativeSingular, AppResources.CommentNominativePlural, AppResources.CommentGenitiveSingular, AppResources.CommentGenitivePlural, null, null).ToLower(CultureInfo.get_CurrentUICulture());
            //});
            _actionsCache.Add(typeof(TLMessageActionChatMigrateTo), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) =>
            {
                var channelId = ((TLMessageActionChatMigrateTo)action).ChannelId;
                var channel   = InMemoryCacheService.Current.GetChat(channelId) as TLChannel;
                var fullName  = channel != null ? channel.DisplayName : string.Empty;
                if (string.IsNullOrWhiteSpace(fullName))
                {
                    return(ReplaceLinks(message, AppResources.MessageActionChatMigrateToGeneric));
                }

                return(ReplaceLinks(message, AppResources.MessageActionChatMigrateTo, new[] { fullName }, new[] { "tg-channel://" + channelId }, useActiveLinks));
            });
            _actionsCache.Add(typeof(TLMessageActionChannelMigrateFrom), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) => ReplaceLinks(message, AppResources.MessageActionChannelMigrateFrom));
            _actionsCache.Add(typeof(TLMessageActionHistoryClear), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) => ReplaceLinks(message, "History was cleared"));
            _actionsCache.Add(typeof(TLMessageActionUnreadMessages), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) => ReplaceLinks(message, "Unread messages"));
            _actionsCache.Add(typeof(TLMessageActionPhoneCall), (TLMessageService message, TLMessageActionBase action, int fromUserId, string fromUserFullName, bool useActiveLinks) =>
            {
                if (message is TLMessageService serviceMessage && action is TLMessageActionPhoneCall phoneCallAction)
                {
                    var loader = ResourceLoader.GetForCurrentView("Resources");
                    var text   = string.Empty;

                    var outgoing = serviceMessage.IsOut;
                    var missed   = phoneCallAction.Reason is TLPhoneCallDiscardReasonMissed || phoneCallAction.Reason is TLPhoneCallDiscardReasonBusy;

                    var type     = loader.GetString(missed ? (outgoing ? "CallCanceled" : "CallMissed") : (outgoing ? "CallOutgoing" : "CallIncoming"));
                    var duration = string.Empty;

                    if (!missed && (phoneCallAction.Duration ?? 0) > 0)
                    {
                        duration = BindConvert.Current.CallDuration(phoneCallAction.Duration ?? 0);
                    }

                    return(ReplaceLinks(serviceMessage, missed || (phoneCallAction.Duration ?? 0) < 1 ? type : string.Format(AppResources.CallTimeFormat, type, duration)));
                }

                return(null);
            });
        private async void OnViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
        {
            if (Messages.ScrollingHost.ScrollableHeight - Messages.ScrollingHost.VerticalOffset < 120)
            {
                //if (ViewModel.IsFirstSliceLoaded)
                //{
                //    Messages.SetScrollMode(ItemsUpdatingScrollMode.KeepLastItemInView, false);
                //}
                //else
                //{
                //    Messages.SetScrollMode(ItemsUpdatingScrollMode.KeepItemsInView, true);
                //}

                Arrow.Visibility = Visibility.Collapsed;
            }
            else
            {
                Arrow.Visibility = Visibility.Visible;
            }

            //if (ViewModel.Peer is TLInputPeerUser)
            //{
            //    lvDialogs.ScrollingHost.ViewChanged -= OnViewChanged;
            //    return;
            //}

            var index0 = _panel.FirstVisibleIndex;
            var index1 = _panel.LastVisibleIndex;

            var show     = false;
            var date     = DateTime.Now;
            var message0 = default(TLMessageCommonBase);

            if (index0 > -1 && index1 > -1 /*&& (index0 != _lastIndex0 || index1 != _lastIndex1)*/ && !e.IsIntermediate)
            {
                var container0 = Messages.ContainerFromIndex(index0);
                if (container0 != null)
                {
                    var item0 = Messages.ItemFromContainer(container0);
                    if (item0 != null)
                    {
                        message0 = item0 as TLMessageCommonBase;
                        var date0 = BindConvert.Current.DateTime(message0.Date);

                        var service0 = message0 as TLMessageService;
                        if (service0 != null)
                        {
                            show = !(service0.Action is TLMessageActionDate);
                        }
                        else
                        {
                            show = true;
                        }

                        date = date0.Date;
                    }
                }

                var mentionIds = new TLVector <int>();
                var unreadId   = 0;
                var dialog     = ViewModel.Dialog;

                var messages = new List <TLMessage>(index1 - index0);
                var auto     = ApplicationSettings.Current.IsAutoPlayEnabled;
                var news     = new Dictionary <string, MediaPlayerItem>();

                for (int i = index0; i <= index1; i++)
                {
                    var container = Messages.ContainerFromIndex(i) as ListViewItem;
                    if (container != null)
                    {
                        var item = Messages.ItemFromContainer(container);
                        if (item is TLMessageCommonBase commonMessage && !commonMessage.IsOut)
                        {
                            //if (/*commonMessage.IsUnread ||*/ commonMessage.Id > dialog?.ReadInboxMaxId)
                            //{
                            //    commonMessage.SetUnread(false);

                            //    unreadId = commonMessage.Id > unreadId ? commonMessage.Id : unreadId;
                            //}

                            if (commonMessage.IsMentioned && commonMessage.IsMediaUnread)
                            {
                                commonMessage.IsMediaUnread = false;
                                commonMessage.RaisePropertyChanged(() => commonMessage.IsMediaUnread);

                                mentionIds.Add(commonMessage.Id);
                            }
                        }

                        var message = item as TLMessage;
                        if (message == null)
                        {
                            continue;
                        }

                        messages.Add(message);
                    }
                }

                Play(messages, auto);

                //if (unreadId > 0)
                //{
                //    if (dialog != null)
                //    {
                //        dialog.UnreadCount = Math.Max(0, dialog.UnreadCount - 1 - ViewModel.Items.Count(x => x.Id > dialog.ReadInboxMaxId && x.Id < unreadId));
                //        dialog.RaisePropertyChanged(() => dialog.UnreadCount);

                //        dialog.ReadInboxMaxId = unreadId;
                //    }

                //    var container = Messages.ContainerFromItem(ViewModel.Items.FirstOrDefault(x => x.Id == unreadId)) as ListViewItem;
                //    var bubble = container.Descendants<MessageBubble>().FirstOrDefault() as MessageBubble;
                //    if (bubble != null)
                //    {
                //        bubble.Highlight();
                //    }

                //    if (ViewModel.With is TLChannel channel)
                //    {
                //        ViewModel.ProtoService.ReadHistoryAsync(channel, unreadId, null);
                //    }
                //    else
                //    {
                //        ViewModel.ProtoService.ReadHistoryAsync(ViewModel.Peer, unreadId, 0, null);
                //    }
                //}

                if (mentionIds.Count > 0)
                {
                    if (dialog != null)
                    {
                        dialog.UnreadMentionsCount = Math.Max(0, dialog.UnreadMentionsCount - mentionIds.Count);
                        dialog.RaisePropertyChanged(() => dialog.UnreadMentionsCount);
                    }

                    if (ViewModel.With is TLChannel channel)
                    {
                        ViewModel.ProtoService.ReadMessageContentsAsync(channel.ToInputChannel(), mentionIds, null);
                    }
                    else
                    {
                        ViewModel.ProtoService.ReadMessageContentsAsync(mentionIds, null);
                    }
                }
            }

            if (show)
            {
                var paragraph = new Paragraph();
                paragraph.Inlines.Add(new Run {
                    Text = DateTimeToFormatConverter.ConvertDayGrouping(date)
                });

                DateHeader.DataContext = message0;
                DateHeader.Visibility  = Visibility.Visible;
                DateHeaderLabel.Blocks.Clear();
                DateHeaderLabel.Blocks.Add(paragraph);
            }
            else
            {
                DateHeader.Visibility = Visibility.Collapsed;
            }

            if (e.IsIntermediate == false)
            {
                await Task.Delay(4000);

                DateHeader.Visibility = Visibility.Collapsed;
            }
        }