< Summary

Class:ChatEntry
Assembly:ChatHUD
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/ChatWidgetHUD/ChatEntry.cs
Covered lines:67
Uncovered lines:48
Coverable lines:115
Total lines:290
Line coverage:58.2% (67 of 115)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ChatEntry()0%110100%
Populate(...)0%42.9325069.39%
OnPointerClick(...)0%90900%
OnPointerEnter(...)0%2100%
OnPointerExit(...)0%220100%
OnDisable()0%110100%
SetFadeout(...)0%2.382054.55%
Update()0%110100%
Fade()0%7.933018.18%
ProcessHoverPanelTimer()0%9.834028.57%
RemoveTabs(...)0%2.152066.67%
GetDefaultSenderString(...)0%2.152066.67%
UnixTimeStampToLocalDateTime(...)0%110100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/ChatWidgetHUD/ChatEntry.cs

#LineLine coverage
 1using DCL.Helpers;
 2using DCL.Interface;
 3using System;
 4using TMPro;
 5using UnityEngine;
 6using UnityEngine.Events;
 7using UnityEngine.EventSystems;
 8using UnityEngine.Serialization;
 9
 10public class ChatEntry : MonoBehaviour, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler
 11{
 12    public struct Model
 13    {
 14        public enum SubType
 15        {
 16            NONE,
 17            PRIVATE_FROM,
 18            PRIVATE_TO
 19        }
 20
 21        public ChatMessage.Type messageType;
 22        public string bodyText;
 23        public string senderId;
 24        public string senderName;
 25        public string recipientName;
 26        public string otherUserId;
 27        public ulong timestamp;
 28
 29        public SubType subType;
 30    }
 31
 3732    [SerializeField] internal float timeToFade = 10f;
 3733    [SerializeField] internal float fadeDuration = 5f;
 34
 35    [SerializeField] internal TextMeshProUGUI username;
 36    [SerializeField] internal TextMeshProUGUI body;
 37
 3738    [SerializeField] internal Color worldMessageColor = Color.white;
 39
 40    [FormerlySerializedAs("privateMessageColor")]
 3741    [SerializeField] internal Color privateToMessageColor = Color.white;
 42
 43    [FormerlySerializedAs("privateMessageColor")]
 3744    [SerializeField] internal Color privateFromMessageColor = Color.white;
 45
 3746    [SerializeField] internal Color systemColor = Color.white;
 3747    [SerializeField] internal Color playerNameColor = Color.yellow;
 3748    [SerializeField] internal Color nonPlayerNameColor = Color.white;
 49    [SerializeField] CanvasGroup group;
 3750    [SerializeField] internal float timeToHoverPanel = 1f;
 51
 52    [NonSerialized] public string messageLocalDateTime;
 53
 54    bool fadeEnabled = false;
 55    double fadeoutStartTime;
 56    float hoverPanelTimer = 0;
 57
 58    public RectTransform hoverPanelPositionReference;
 59    public RectTransform contextMenuPositionReference;
 60
 061    public Model model { get; private set; }
 62
 63    public event UnityAction<string> OnPress;
 64    public event UnityAction<ChatEntry> OnPressRightButton;
 65    public event UnityAction<ChatEntry> OnTriggerHover;
 66    public event UnityAction OnCancelHover;
 67
 68    public void Populate(Model chatEntryModel)
 69    {
 3270        this.model = chatEntryModel;
 71
 3272        string userString = GetDefaultSenderString(chatEntryModel.senderName);
 73
 3274        if (chatEntryModel.subType == Model.SubType.PRIVATE_FROM)
 75        {
 676            userString = $"<b>From {chatEntryModel.senderName}:</b>";
 677        }
 2678        else if (chatEntryModel.subType == Model.SubType.PRIVATE_TO)
 79        {
 280            userString = $"<b>To {chatEntryModel.recipientName}:</b>";
 81        }
 82
 3283        switch (chatEntryModel.messageType)
 84        {
 85            case ChatMessage.Type.PUBLIC:
 1886                body.color = worldMessageColor;
 87
 1888                if (username != null)
 1889                    username.color = chatEntryModel.senderName == UserProfile.GetOwnUserProfile().userName ? playerNameC
 1890                break;
 91            case ChatMessage.Type.PRIVATE:
 1392                body.color = worldMessageColor;
 93
 1394                if (username != null)
 95                {
 696                    if (model.subType == Model.SubType.PRIVATE_TO)
 297                        username.color = privateToMessageColor;
 98                    else
 499                        username.color = privateFromMessageColor;
 100                }
 101
 4102                break;
 103            case ChatMessage.Type.SYSTEM:
 1104                body.color = systemColor;
 105
 1106                if (username != null)
 1107                    username.color = systemColor;
 108                break;
 109        }
 110
 32111        chatEntryModel.bodyText = RemoveTabs(chatEntryModel.bodyText);
 112
 32113        if (username != null && !string.IsNullOrEmpty(userString))
 114        {
 25115            if (username != null)
 25116                username.text = userString;
 117
 25118            body.text = $"{userString} {chatEntryModel.bodyText}";
 25119        }
 120        else
 121        {
 7122            if (username != null)
 0123                username.text = "";
 124
 7125            body.text = $"{chatEntryModel.bodyText}";
 126        }
 127
 32128        messageLocalDateTime = UnixTimeStampToLocalDateTime(chatEntryModel.timestamp).ToString();
 129
 32130        Utils.ForceUpdateLayout(transform as RectTransform);
 131
 32132        if (fadeEnabled)
 0133            group.alpha = 0;
 134
 32135        if (HUDAudioHandler.i != null)
 136        {
 137            // Check whether or not this message is new, and chat sounds are enabled in settings
 0138            if (chatEntryModel.timestamp > HUDAudioHandler.i.chatLastCheckedTimestamp && DCL.Settings.i.currentAudioSett
 139            {
 0140                switch (chatEntryModel.messageType)
 141                {
 142                    case ChatMessage.Type.PUBLIC:
 143                        // Check whether or not the message was sent by the local player
 0144                        if (chatEntryModel.senderId == UserProfile.GetOwnUserProfile().userId)
 0145                            AudioScriptableObjects.chatSend.Play(true);
 146                        else
 0147                            AudioScriptableObjects.chatReceiveGlobal.Play(true);
 0148                        break;
 149                    case ChatMessage.Type.PRIVATE:
 0150                        switch (chatEntryModel.subType)
 151                        {
 152                            case Model.SubType.PRIVATE_FROM:
 0153                                AudioScriptableObjects.chatReceivePrivate.Play(true);
 0154                                break;
 155                            case Model.SubType.PRIVATE_TO:
 0156                                AudioScriptableObjects.chatSend.Play(true);
 0157                                break;
 158                            default:
 159                                break;
 160                        }
 161                        break;
 162                    case ChatMessage.Type.SYSTEM:
 0163                        AudioScriptableObjects.chatReceiveGlobal.Play(true);
 164                        break;
 165                    default:
 166                        break;
 167                }
 168            }
 169
 0170            HUDAudioHandler.i.RefreshChatLastCheckedTimestamp();
 171        }
 32172    }
 173
 174    public void OnPointerClick(PointerEventData pointerEventData)
 175    {
 0176        if (pointerEventData.button == PointerEventData.InputButton.Left)
 177        {
 0178            if (model.messageType != ChatMessage.Type.PRIVATE)
 0179                return;
 180
 0181            OnPress?.Invoke(model.otherUserId);
 0182        }
 0183        else if (pointerEventData.button == PointerEventData.InputButton.Right)
 184        {
 0185            if ((model.messageType != ChatMessage.Type.PUBLIC && model.messageType != ChatMessage.Type.PRIVATE) ||
 186                model.senderId == UserProfile.GetOwnUserProfile().userId)
 0187                return;
 188
 0189            OnPressRightButton?.Invoke(this);
 190        }
 0191    }
 192
 0193    public void OnPointerEnter(PointerEventData pointerEventData) { hoverPanelTimer = timeToHoverPanel; }
 194
 195    public void OnPointerExit(PointerEventData pointerEventData)
 196    {
 29197        hoverPanelTimer = 0f;
 198
 29199        OnCancelHover?.Invoke();
 28200    }
 201
 58202    void OnDisable() { OnPointerExit(null); }
 203
 204    public void SetFadeout(bool enabled)
 205    {
 29206        if (!enabled)
 207        {
 29208            group.alpha = 1;
 29209            group.blocksRaycasts = true;
 29210            group.interactable = true;
 29211            fadeEnabled = false;
 29212            return;
 213        }
 214
 0215        fadeoutStartTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() / 1000.0;
 0216        fadeEnabled = true;
 0217        group.blocksRaycasts = false;
 0218        group.interactable = false;
 0219    }
 220
 221    void Update()
 222    {
 3223        Fade();
 224
 3225        ProcessHoverPanelTimer();
 3226    }
 227
 228    void Fade()
 229    {
 3230        if (!fadeEnabled)
 3231            return;
 232
 233        //NOTE(Brian): Small offset using normalized Y so we keep the cascade effect
 0234        double yOffset = (transform as RectTransform).anchoredPosition.y / (double)Screen.height * 2.0;
 235
 0236        double fadeTime = Math.Max(model.timestamp / 1000.0, fadeoutStartTime) + timeToFade - yOffset;
 0237        double currentTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() / 1000.0;
 238
 0239        if (currentTime > fadeTime)
 240        {
 0241            double timeSinceFadeTime = currentTime - fadeTime;
 0242            group.alpha = Mathf.Clamp01(1 - (float)(timeSinceFadeTime / fadeDuration));
 0243        }
 244        else
 245        {
 0246            group.alpha += (1 - group.alpha) * 0.05f;
 247        }
 0248    }
 249
 250    void ProcessHoverPanelTimer()
 251    {
 3252        if (hoverPanelTimer <= 0f)
 3253            return;
 254
 0255        hoverPanelTimer -= Time.deltaTime;
 0256        if (hoverPanelTimer <= 0f)
 257        {
 0258            hoverPanelTimer = 0f;
 259
 0260            OnTriggerHover?.Invoke(this);
 261        }
 0262    }
 263
 264    string RemoveTabs(string text)
 265    {
 32266        if (string.IsNullOrEmpty(text))
 0267            return "";
 268
 269        //NOTE(Brian): ContentSizeFitter doesn't fare well with tabs, so i'm replacing these
 270        //             with spaces.
 32271        return text.Replace("\t", "    ");
 272    }
 273
 274    string GetDefaultSenderString(string sender)
 275    {
 32276        if (!string.IsNullOrEmpty(sender))
 32277            return $"<b>{sender}:</b>";
 278
 0279        return "";
 280    }
 281
 282    DateTime UnixTimeStampToLocalDateTime(ulong unixTimeStampMilliseconds)
 283    {
 284        // TODO see if we can simplify with 'DateTimeOffset.FromUnixTimeMilliseconds'
 32285        System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
 32286        dtDateTime = dtDateTime.AddMilliseconds(unixTimeStampMilliseconds).ToLocalTime();
 287
 32288        return dtDateTime;
 289    }
 290}