< Summary

Class:DCL.Chat.Notifications.MainChatNotificationsComponentView
Assembly:NotificationMessagesHUD
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/NotificationMessagesHUD/MainChatNotificationsComponentView.cs
Covered lines:111
Uncovered lines:42
Coverable lines:153
Total lines:313
Line coverage:72.5% (111 of 153)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
MainChatNotificationsComponentView()0%110100%
Create()0%110100%
Awake()0%330100%
Show(...)0%110100%
Hide(...)0%110100%
GetPanelTransform()0%2100%
ResetNotificationButtonFromScroll(...)0%6200%
ShowPanel()0%12300%
HidePanel()0%12300%
ShowNotifications()0%6200%
HideNotifications()0%6200%
AddNewChatNotification(...)0%4.024088.89%
AddNewChatNotification(...)0%4.024088.89%
AnimateNewEntry()0%8.126061.11%
ResetNotificationButton()0%220100%
IncreaseNotificationCount()0%20400%
SetScrollToEnd(...)0%110100%
PopulatePrivateNotification(...)0%2.012087.5%
PopulatePublicNotification(...)0%220100%
ClickedOnNotification(...)0%6200%
FocusedOnNotification(...)0%3.333066.67%
FocusedOnPanel(...)0%4.254075%
CheckNotificationCountAndRelease()0%2.862040%
GetNotificationEntryPool()0%2.022083.33%
RefreshControl()0%2100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/NotificationMessagesHUD/MainChatNotificationsComponentView.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Threading;
 4using Cysharp.Threading.Tasks;
 5using DCL.Helpers;
 6using DCL.Interface;
 7using DG.Tweening;
 8using TMPro;
 9using UnityEngine;
 10using UnityEngine.UI;
 11
 12namespace DCL.Chat.Notifications
 13{
 14    public class MainChatNotificationsComponentView : BaseComponentView, IMainChatNotificationsComponentView
 15    {
 16        [SerializeField] private RectTransform chatEntriesContainer;
 17        [SerializeField] private GameObject chatNotification;
 18        [SerializeField] private ScrollRect scrollRectangle;
 19        [SerializeField] private Button notificationButton;
 20        [SerializeField] private ShowHideAnimator panelAnimator;
 21        [SerializeField] private ShowHideAnimator scrollbarAnimator;
 22
 23        private const string NOTIFICATION_POOL_NAME_PREFIX = "NotificationEntriesPool_";
 24        private const int MAX_NOTIFICATION_ENTRIES = 30;
 25
 26        public event Action<string> OnClickedNotification;
 27        public event Action<bool> OnResetFade;
 28        public event Action<bool> OnPanelFocus;
 29
 730        internal readonly Queue<PoolableObject> poolableQueue = new Queue<PoolableObject>();
 31
 732        internal readonly Queue<ChatNotificationMessageComponentView> notificationQueue =
 33            new Queue<ChatNotificationMessageComponentView>();
 34
 735        private readonly Vector2 notificationOffset = new Vector2(0, -56);
 36
 37        private Pool entryPool;
 38        private bool isOverMessage;
 39        private bool isOverPanel;
 740        private int notificationCount = 1;
 41        private TMP_Text notificationMessage;
 742        private CancellationTokenSource animationCancellationToken = new CancellationTokenSource();
 143        private BaseVariable<string> openedChat => DataStore.i.HUDs.openedChat;
 44
 45        public static MainChatNotificationsComponentView Create()
 46        {
 647            return Instantiate(Resources.Load<MainChatNotificationsComponentView>("SocialBarV1/ChatNotificationHUD"));
 48        }
 49
 50        public void Awake()
 51        {
 652            onFocused += FocusedOnPanel;
 653            notificationMessage = notificationButton.GetComponentInChildren<TMP_Text>();
 654            notificationButton?.onClick.RemoveAllListeners();
 655            notificationButton?.onClick.AddListener(() => SetScrollToEnd());
 656            scrollRectangle.onValueChanged.AddListener(ResetNotificationButtonFromScroll);
 657        }
 58
 59        public override void Show(bool instant = false)
 60        {
 161            openedChat.Set("");
 162            gameObject.SetActive(true);
 163        }
 64
 65        public override void Hide(bool instant = false)
 66        {
 167            SetScrollToEnd();
 168            gameObject.SetActive(false);
 169        }
 70
 71        public Transform GetPanelTransform()
 72        {
 073            return gameObject.transform;
 74        }
 75
 76        private void ResetNotificationButtonFromScroll(Vector2 newValue)
 77        {
 078            if (newValue.y <= 0.0)
 79            {
 080                ResetNotificationButton();
 81            }
 082        }
 83
 84        public void ShowPanel()
 85        {
 086            panelAnimator?.Show();
 087            scrollbarAnimator?.Show();
 088        }
 89
 90        public void HidePanel()
 91        {
 092            panelAnimator?.Hide();
 093            scrollbarAnimator?.Hide();
 094        }
 95
 96        public void ShowNotifications()
 97        {
 098            foreach (ChatNotificationMessageComponentView notification in notificationQueue)
 99            {
 0100                notification.Show();
 101            }
 0102        }
 103
 104        public void HideNotifications()
 105        {
 0106            foreach (ChatNotificationMessageComponentView notification in notificationQueue)
 107            {
 0108                notification.Hide();
 109            }
 0110        }
 111
 112        public void AddNewChatNotification(PrivateChatMessageNotificationModel model)
 113        {
 1114            entryPool = GetNotificationEntryPool();
 1115            var newNotification = entryPool.Get();
 116
 1117            var entry = newNotification.gameObject.GetComponent<ChatNotificationMessageComponentView>();
 1118            poolableQueue.Enqueue(newNotification);
 1119            notificationQueue.Enqueue(entry);
 120
 1121            entry.OnClickedNotification -= ClickedOnNotification;
 1122            entry.onFocused -= FocusedOnNotification;
 1123            entry.showHideAnimator.OnWillFinishHide -= SetScrollToEnd;
 124
 1125            PopulatePrivateNotification(entry, model);
 126
 1127            entry.transform.SetParent(chatEntriesContainer, false);
 1128            entry.RefreshControl();
 1129            entry.SetTimestamp(Utils.UnixTimeStampToLocalTime(model.Timestamp));
 1130            entry.OnClickedNotification += ClickedOnNotification;
 1131            entry.onFocused += FocusedOnNotification;
 1132            entry.showHideAnimator.OnWillFinishHide += SetScrollToEnd;
 133
 1134            chatEntriesContainer.anchoredPosition += notificationOffset;
 1135            if (isOverPanel)
 136            {
 0137                notificationButton.gameObject.SetActive(true);
 0138                IncreaseNotificationCount();
 0139            }
 140            else
 141            {
 1142                ResetNotificationButton();
 1143                animationCancellationToken.Cancel();
 1144                animationCancellationToken = new CancellationTokenSource();
 1145                AnimateNewEntry(entry.gameObject.transform, animationCancellationToken.Token).Forget();
 146            }
 147
 1148            OnResetFade?.Invoke(!isOverMessage && !isOverPanel);
 1149            CheckNotificationCountAndRelease();
 1150        }
 151
 152        public void AddNewChatNotification(PublicChannelMessageNotificationModel model)
 153        {
 2154            entryPool = GetNotificationEntryPool();
 2155            var newNotification = entryPool.Get();
 156
 2157            var entry = newNotification.gameObject.GetComponent<ChatNotificationMessageComponentView>();
 2158            poolableQueue.Enqueue(newNotification);
 2159            notificationQueue.Enqueue(entry);
 160
 2161            entry.OnClickedNotification -= ClickedOnNotification;
 2162            entry.onFocused -= FocusedOnNotification;
 2163            entry.showHideAnimator.OnWillFinishHide -= SetScrollToEnd;
 164
 2165            PopulatePublicNotification(entry, model);
 166
 2167            entry.transform.SetParent(chatEntriesContainer, false);
 2168            entry.RefreshControl();
 2169            entry.SetTimestamp(Utils.UnixTimeStampToLocalTime(model.Timestamp));
 2170            entry.OnClickedNotification += ClickedOnNotification;
 2171            entry.onFocused += FocusedOnNotification;
 2172            entry.showHideAnimator.OnWillFinishHide += SetScrollToEnd;
 173
 2174            chatEntriesContainer.anchoredPosition += notificationOffset;
 2175            if (isOverPanel)
 176            {
 0177                notificationButton.gameObject.SetActive(true);
 0178                IncreaseNotificationCount();
 0179            }
 180            else
 181            {
 2182                ResetNotificationButton();
 2183                animationCancellationToken.Cancel();
 2184                animationCancellationToken = new CancellationTokenSource();
 2185                AnimateNewEntry(entry.gameObject.transform, animationCancellationToken.Token).Forget();
 186            }
 187
 2188            OnResetFade?.Invoke(!isOverMessage && !isOverPanel);
 2189            CheckNotificationCountAndRelease();
 2190        }
 191
 192        private async UniTaskVoid AnimateNewEntry(Transform notification, CancellationToken cancellationToken)
 193        {
 3194            cancellationToken.ThrowIfCancellationRequested();
 3195            Sequence mySequence = DOTween.Sequence().AppendInterval(0.2f)
 196                .Append(notification.DOScale(1, 0.3f).SetEase(Ease.OutBack));
 197            try
 198            {
 3199                Vector2 endPosition = new Vector2(0, 0);
 3200                Vector2 currentPosition = chatEntriesContainer.anchoredPosition;
 3201                notification.localScale = Vector3.zero;
 105202                DOTween.To(() => currentPosition, x => currentPosition = x, endPosition, 0.8f).SetEase(Ease.OutCubic);
 6203                while (chatEntriesContainer.anchoredPosition.y < 0)
 204                {
 3205                    chatEntriesContainer.anchoredPosition = currentPosition;
 9206                    await UniTask.NextFrame(cancellationToken);
 207                }
 208
 0209                mySequence.Play();
 0210            }
 0211            catch (OperationCanceledException)
 212            {
 0213                if (!DOTween.IsTweening(notification))
 0214                    notification.DOScale(1, 0.3f).SetEase(Ease.OutBack);
 0215            }
 0216        }
 217
 218        private void ResetNotificationButton()
 219        {
 4220            notificationButton.gameObject.SetActive(false);
 4221            notificationCount = 0;
 222
 4223            if (notificationMessage != null)
 4224                notificationMessage.text = notificationCount.ToString();
 4225        }
 226
 227        private void IncreaseNotificationCount()
 228        {
 0229            notificationCount++;
 0230            if (notificationMessage != null)
 0231                notificationMessage.text = notificationCount <= 9 ? notificationCount.ToString() : "9+";
 0232        }
 233
 234        private void SetScrollToEnd(ShowHideAnimator animator = null)
 235        {
 1236            scrollRectangle.normalizedPosition = new Vector2(0, 0);
 1237            ResetNotificationButton();
 1238        }
 239
 240        private void PopulatePrivateNotification(ChatNotificationMessageComponentView chatNotificationComponentView,
 241            PrivateChatMessageNotificationModel model)
 242        {
 1243            chatNotificationComponentView.SetIsPrivate(true);
 1244            chatNotificationComponentView.SetMessage(model.Body);
 1245            chatNotificationComponentView.SetNotificationHeader("Private message");
 1246            chatNotificationComponentView.SetNotificationSender($"{model.Username}:");
 1247            chatNotificationComponentView.SetNotificationTargetId(model.SenderId);
 1248            if (!string.IsNullOrEmpty(model.ProfilePicture))
 0249                chatNotificationComponentView.SetImage(model.ProfilePicture);
 1250        }
 251
 252        private void PopulatePublicNotification(ChatNotificationMessageComponentView chatNotificationComponentView,
 253            PublicChannelMessageNotificationModel model)
 254        {
 2255            chatNotificationComponentView.SetIsPrivate(false);
 2256            chatNotificationComponentView.SetMessage(model.Body);
 257
 2258            var channelId = model.ChannelId;
 2259            var channelName = model.ChannelName == "nearby" ? "~nearby" : $"#{model.ChannelName}";
 260
 2261            chatNotificationComponentView.SetNotificationTargetId(channelId);
 2262            chatNotificationComponentView.SetNotificationHeader(channelName);
 2263            chatNotificationComponentView.SetNotificationSender($"{model.Username}:");
 2264        }
 265
 266        private void ClickedOnNotification(string targetId)
 267        {
 0268            OnClickedNotification?.Invoke(targetId);
 0269        }
 270
 271        private void FocusedOnNotification(bool isInFocus)
 272        {
 3273            isOverMessage = isInFocus;
 3274            OnResetFade?.Invoke(!isOverMessage && !isOverPanel);
 0275        }
 276
 277        private void FocusedOnPanel(bool isInFocus)
 278        {
 6279            isOverPanel = isInFocus;
 6280            OnPanelFocus?.Invoke(isOverPanel);
 6281            OnResetFade?.Invoke(!isOverMessage && !isOverPanel);
 0282        }
 283
 284        private void CheckNotificationCountAndRelease()
 285        {
 3286            if (poolableQueue.Count >= MAX_NOTIFICATION_ENTRIES)
 287            {
 0288                ChatNotificationMessageComponentView notificationToDequeue = notificationQueue.Dequeue();
 0289                notificationToDequeue.onFocused -= FocusedOnNotification;
 0290                entryPool.Release(poolableQueue.Dequeue());
 291            }
 3292        }
 293
 294        private Pool GetNotificationEntryPool()
 295        {
 3296            var entryPool = PoolManager.i.GetPool(NOTIFICATION_POOL_NAME_PREFIX + name + GetInstanceID());
 3297            if (entryPool != null) return entryPool;
 298
 3299            entryPool = PoolManager.i.AddPool(
 300                NOTIFICATION_POOL_NAME_PREFIX + name + GetInstanceID(),
 301                Instantiate(chatNotification).gameObject,
 302                maxPrewarmCount: MAX_NOTIFICATION_ENTRIES,
 303                isPersistent: true);
 3304            entryPool.ForcePrewarm();
 305
 3306            return entryPool;
 307        }
 308
 309        public override void RefreshControl()
 310        {
 0311        }
 312    }
 313}