< Summary

Class:NFTPromptHUDView
Assembly:NFTPromptHUD
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/NFTPromptHUD/NFTPromptHUDView.cs
Covered lines:73
Uncovered lines:134
Coverable lines:207
Total lines:476
Line coverage:35.2% (73 of 207)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Awake()0%110100%
Dispose()0%220100%
Hide()0%2.012085.71%
GetOwnersPopup()0%110100%
GetOwnersTooltip()0%110100%
SetActive(...)0%110100%
IsActive()0%110100%
GetOwnerElementPrefab()0%110100%
SetLoading()0%22095.65%
SetNFTInfo(...)0%1821300%
Show()0%110100%
FetchNFTImage()0%1321100%
SetNFTImageSize(...)0%6200%
ShortDecimals(...)0%30500%
SetSmartBackgroundColor(...)0%2100%
SetTokenSymbol(...)0%2100%
OpenMarketUrl()0%6200%
OnError(...)0%2100%
OnDestroy()0%110100%
ForgetPromises()0%3.333066.67%
SetupGifPlayer(...)0%6200%
OnViewAllOwnersPressed()0%6200%
OnOwnersTooltipGainFocus()0%6200%
OnOwnersTooltipLostFocus()0%6200%
OnOwnersPopupClose()0%6200%
OwnerLabelPointerEnter()0%6200%
OwnerLabelPointerExit()0%6200%
ShowMainLoading(...)0%2.062075%
ShowMainErrorFeedback(...)0%3.333066.67%
ShowImageLoading(...)0%2.062075%
ShowImageErrorFeedback(...)0%12300%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/NFTPromptHUD/NFTPromptHUDView.cs

#LineLine coverage
 1using System;
 2using UnityEngine;
 3using UnityEngine.UI;
 4using TMPro;
 5using DCL;
 6using DCL.Helpers;
 7using DCL.Helpers.NFT;
 8using DCL.Interface;
 9using System.Collections;
 10
 11internal interface INFTPromptHUDView : IDisposable
 12{
 13    event Action OnOwnerLabelPointerEnter;
 14    event Action OnOwnerLabelPointerExit;
 15    event Action OnOwnersTooltipFocusLost;
 16    event Action OnOwnersTooltipFocus;
 17    event Action OnViewAllPressed;
 18    event Action OnOwnersPopupClosed;
 19    void SetActive(bool active);
 20    bool IsActive();
 21    IOwnersTooltipView GetOwnersTooltip();
 22    IOwnersPopupView GetOwnersPopup();
 23    OwnerInfoElement GetOwnerElementPrefab();
 24    void SetLoading();
 25    void SetNFTInfo(NFTInfoSingleAsset info, string comment);
 26    void OnError(string error);
 27}
 28
 29internal class NFTPromptHUDView : MonoBehaviour, INFTPromptHUDView
 30{
 31    private const string MULTIPLE_OWNERS_FORMAT = "{0} owners";
 32    private const int ADDRESS_MAX_CHARS = 11;
 33
 34    public event Action OnOwnerLabelPointerEnter;
 35    public event Action OnOwnerLabelPointerExit;
 36    public event Action OnOwnersTooltipFocusLost;
 37    public event Action OnOwnersTooltipFocus;
 38    public event Action OnViewAllPressed;
 39    public event Action OnOwnersPopupClosed;
 40
 41    [SerializeField] internal GameObject content;
 42    [SerializeField] internal GameObject nftContent;
 43    [SerializeField] internal GameObject mainErrorFeedbackContent;
 44    [SerializeField] internal GameObject imageErrorFeedbackContent;
 45
 46    [SerializeField] RawImage imageNft;
 47    [SerializeField] Image imageNftBackground;
 48    [SerializeField] TextMeshProUGUI textNftName;
 49    [SerializeField] TextMeshProUGUI textOwner;
 50    [SerializeField] TextMeshProUGUI textMultipleOwner;
 51    [SerializeField] UIHoverCallback multipleOwnersContainer;
 52
 53    [Header("Last Sale")] [SerializeField] TextMeshProUGUI textLastSaleSymbol;
 54    [SerializeField] TextMeshProUGUI textLastSalePrice;
 55    [SerializeField] TextMeshProUGUI textLastSaleNeverSold;
 56
 57    [Header("Price")] [SerializeField] TextMeshProUGUI textPriceSymbol;
 58    [SerializeField] TextMeshProUGUI textPrice;
 59    [SerializeField] TextMeshProUGUI textPriceNotForSale;
 60
 61    [Header("Description & Comment")]
 62    [SerializeField]
 63    TextMeshProUGUI textDescription;
 64
 65    [SerializeField] TextMeshProUGUI textComment;
 66    [SerializeField] GameObject containerDescription;
 67    [SerializeField] GameObject containerComment;
 68
 69    [Header("Spinners")] [SerializeField] GameObject spinnerGeneral;
 70    [SerializeField] GameObject spinnerNftImage;
 71
 72    [Header("Buttons")] [SerializeField] internal Button buttonClose;
 73    [SerializeField] internal Button buttonCancel;
 74    [SerializeField] internal Button buttonOpenMarket;
 75    [SerializeField] TextMeshProUGUI textOpenMarketButton;
 76
 77    [Header("Owners")]
 78    [SerializeField] internal OwnerInfoElement ownerElementPrefab;
 79    [SerializeField] internal OwnersTooltipView ownersTooltip;
 80    [SerializeField] internal OwnersPopupView ownersPopup;
 81
 82    Coroutine fetchNFTImageRoutine = null;
 83
 84    private IPromiseLike_TextureAsset imagePromise = null;
 85    private GifPlayer gifPlayer = null;
 86
 87    private string nftTokenId;
 88    bool backgroundColorSet = false;
 89    string marketUrl = null;
 90
 91    private bool isDestroyed = false;
 92
 93    private void Awake()
 94    {
 795        name = "_NFTPromptHUD";
 96
 797        buttonClose.onClick.AddListener(Hide);
 798        buttonCancel.onClick.AddListener(Hide);
 799        buttonOpenMarket.onClick.AddListener(OpenMarketUrl);
 100
 7101        multipleOwnersContainer.OnPointerEnter += OwnerLabelPointerEnter;
 7102        multipleOwnersContainer.OnPointerExit += OwnerLabelPointerExit;
 7103        ownersTooltip.OnViewAllPressed += OnViewAllOwnersPressed;
 7104        ownersTooltip.OnFocusLost += OnOwnersTooltipLostFocus;
 7105        ownersTooltip.OnFocus += OnOwnersTooltipGainFocus;
 7106        ownersPopup.OnClosePopup += OnOwnersPopupClose;
 7107    }
 108
 109    public void Dispose()
 110    {
 7111        if (!isDestroyed)
 112        {
 7113            Destroy(gameObject);
 114        }
 7115    }
 116
 117    internal void Hide()
 118    {
 1119        content.SetActive(false);
 120
 1121        ForgetPromises();
 122
 1123        if (fetchNFTImageRoutine != null)
 0124            StopCoroutine(fetchNFTImageRoutine);
 125
 1126        fetchNFTImageRoutine = null;
 127
 1128        AudioScriptableObjects.dialogClose.Play(true);
 1129    }
 130
 1131    IOwnersPopupView INFTPromptHUDView.GetOwnersPopup() { return ownersPopup; }
 132
 1133    IOwnersTooltipView INFTPromptHUDView.GetOwnersTooltip() { return ownersTooltip; }
 134
 16135    void INFTPromptHUDView.SetActive(bool active) { content.SetActive(active); }
 136
 1137    bool INFTPromptHUDView.IsActive() { return content.activeSelf; }
 138
 7139    OwnerInfoElement INFTPromptHUDView.GetOwnerElementPrefab() { return ownerElementPrefab; }
 140
 141    void INFTPromptHUDView.SetLoading()
 142    {
 1143        Show();
 144
 1145        if (fetchNFTImageRoutine != null)
 0146            StopCoroutine(fetchNFTImageRoutine);
 147
 1148        imageNftBackground.color = Color.white;
 149
 1150        imageNft.gameObject.SetActive(false);
 1151        textNftName.gameObject.SetActive(false);
 1152        textOwner.gameObject.SetActive(false);
 1153        multipleOwnersContainer.gameObject.SetActive(false);
 1154        textLastSaleSymbol.gameObject.SetActive(false);
 1155        textLastSalePrice.gameObject.SetActive(false);
 1156        textLastSaleNeverSold.gameObject.SetActive(false);
 1157        textPriceSymbol.gameObject.SetActive(false);
 1158        textPrice.gameObject.SetActive(false);
 1159        textPriceNotForSale.gameObject.SetActive(false);
 1160        containerDescription.SetActive(false);
 1161        containerComment.SetActive(false);
 1162        buttonCancel.gameObject.SetActive(false);
 1163        buttonOpenMarket.gameObject.SetActive(false);
 164
 1165        nftContent.SetActive(false);
 1166        ShowImageLoading(false);
 1167        ShowMainLoading(true);
 1168        ShowMainErrorFeedback(false);
 1169    }
 170
 171    void INFTPromptHUDView.SetNFTInfo(NFTInfoSingleAsset info, string comment)
 172    {
 0173        Show();
 174
 0175        ShowMainLoading(false);
 0176        nftContent.SetActive(true);
 177
 0178        nftTokenId = info.tokenId;
 0179        imageNftBackground.color = Color.white;
 0180        backgroundColorSet = info.backgroundColor != null;
 0181        if (backgroundColorSet)
 182        {
 0183            imageNftBackground.color = info.backgroundColor.Value;
 184        }
 185
 0186        textNftName.text = info.name;
 0187        textNftName.gameObject.SetActive(true);
 188
 0189        bool hasMultipleOwners = info.owners.Length > 1;
 0190        if (hasMultipleOwners)
 191        {
 0192            textMultipleOwner.text = string.Format(MULTIPLE_OWNERS_FORMAT, info.owners.Length);
 0193        }
 194        else
 195        {
 0196            textOwner.text = info.owners.Length == 1
 197                ? NFTPromptHUDController.FormatOwnerAddress(info.owners[0].owner, ADDRESS_MAX_CHARS)
 198                : NFTPromptHUDController.FormatOwnerAddress("0x0000000000000000000000000000000000000000", ADDRESS_MAX_CH
 199        }
 0200        textOwner.gameObject.SetActive(!hasMultipleOwners);
 0201        multipleOwnersContainer.gameObject.SetActive(hasMultipleOwners);
 202
 0203        if (!string.IsNullOrEmpty(info.lastSaleAmount))
 204        {
 0205            textLastSalePrice.text = ShortDecimals(info.lastSaleAmount, 4);
 0206            textLastSalePrice.gameObject.SetActive(true);
 0207        }
 208        else
 209        {
 0210            textLastSaleNeverSold.gameObject.SetActive(true);
 211        }
 212
 0213        if (!string.IsNullOrEmpty(info.currentPrice))
 214        {
 0215            textPrice.text = ShortDecimals(info.currentPrice, 4);
 0216            textPrice.gameObject.SetActive(true);
 217
 0218            if (info.currentPriceToken != null)
 219            {
 0220                SetTokenSymbol(textPriceSymbol, info.currentPriceToken.Value.symbol);
 221            }
 0222        }
 223        else
 224        {
 0225            textPriceNotForSale.gameObject.SetActive(true);
 226        }
 227
 0228        if (info.lastSaleToken != null)
 229        {
 0230            SetTokenSymbol(textLastSaleSymbol, info.lastSaleToken.Value.symbol);
 231        }
 232
 0233        if (!string.IsNullOrEmpty(info.description))
 234        {
 0235            textDescription.text = info.description;
 0236            containerDescription.SetActive(true);
 237        }
 238
 0239        if (!string.IsNullOrEmpty(comment))
 240        {
 0241            textComment.text = comment;
 0242            containerComment.SetActive(true);
 243        }
 244
 0245        textOpenMarketButton.text = "VIEW";
 0246        if (info.marketInfo != null)
 247        {
 0248            textOpenMarketButton.text = $"{textOpenMarketButton.text} ON {info.marketInfo.Value.name.ToUpper()}";
 249        }
 250
 0251        marketUrl = null;
 0252        if (!string.IsNullOrEmpty(info.marketLink))
 253        {
 0254            marketUrl = info.marketLink;
 0255        }
 0256        else if (!string.IsNullOrEmpty(info.assetLink))
 257        {
 0258            marketUrl = info.assetLink;
 259        }
 260
 0261        buttonCancel.gameObject.SetActive(true);
 0262        buttonOpenMarket.gameObject.SetActive(true);
 263
 0264        fetchNFTImageRoutine = StartCoroutine(FetchNFTImage(info));
 0265    }
 266
 267    private void Show()
 268    {
 1269        content.SetActive(true);
 1270        Utils.UnlockCursor();
 1271    }
 272
 273    private IEnumerator FetchNFTImage(NFTInfoSingleAsset nftInfo)
 274    {
 0275        ShowImageErrorFeedback(false);
 0276        ShowImageLoading(true);
 277
 0278        bool imageFound = false;
 279
 0280        yield return WrappedTextureUtils.Fetch(nftInfo.previewImageUrl,
 281            promise =>
 282            {
 0283                imagePromise = promise;
 0284                imageFound = true;
 0285            });
 286
 0287        if (!imageFound)
 288        {
 0289            yield return WrappedTextureUtils.Fetch(nftInfo.originalImageUrl,
 290                promise =>
 291                {
 0292                    imagePromise = promise;
 0293                    imageFound = true;
 0294                });
 295        }
 296
 0297        if (imageFound && imagePromise?.asset != null)
 298        {
 0299            Texture2D texture = imagePromise.asset.texture;
 0300            imageNft.texture = texture;
 301
 0302            if ((imagePromise.asset is Asset_Gif gif))
 303            {
 0304                SetupGifPlayer(gif);
 0305            }
 0306            else if (!backgroundColorSet)
 307            {
 0308                SetSmartBackgroundColor(texture);
 309            }
 310
 0311            SetNFTImageSize(texture);
 312
 0313            imageNft.gameObject.SetActive(true);
 0314            ShowImageLoading(false);
 0315        }
 316        else
 317        {
 0318            ShowImageErrorFeedback(true);
 319        }
 0320    }
 321
 322    private void SetNFTImageSize(Texture2D texture)
 323    {
 0324        RectTransform rt = (RectTransform)imageNft.transform.parent;
 325        float h, w;
 0326        if (texture.height > texture.width)
 327        {
 0328            h = rt.rect.height;
 0329            w = h * (texture.width / (float)texture.height);
 0330        }
 331        else
 332        {
 0333            w = rt.rect.width;
 0334            h = w * (texture.height / (float)texture.width);
 335        }
 336
 0337        imageNft.rectTransform.sizeDelta = new Vector2(w, h);
 0338    }
 339
 340    private string ShortDecimals(string value, int decimalCount)
 341    {
 0342        int pointPosition = value.IndexOf('.');
 0343        if (pointPosition <= 0)
 0344            return value;
 345
 0346        string ret = value.Substring(0, pointPosition + Mathf.Min(value.Length - pointPosition, decimalCount + 1));
 347
 0348        for (int i = ret.Length - 1; i >= 0; i--)
 349        {
 0350            if (ret[i] == '.')
 351            {
 0352                return ret.Substring(0, i);
 353            }
 354
 0355            if (ret[i] != '0')
 356            {
 0357                return ret.Substring(0, i + 1);
 358            }
 359        }
 360
 0361        return ret;
 362    }
 363
 0364    private void SetSmartBackgroundColor(Texture2D texture) { imageNftBackground.color = texture.GetPixel(0, 0); }
 365
 366    private void SetTokenSymbol(TextMeshProUGUI textToken, string symbol)
 367    {
 0368        textToken.text = symbol;
 0369        textToken.gameObject.SetActive(true);
 0370    }
 371
 372    private void OpenMarketUrl()
 373    {
 0374        if (!string.IsNullOrEmpty(marketUrl))
 375        {
 0376            WebInterface.OpenURL(marketUrl);
 0377            AnalyticsHelper.SendExternalLinkAnalytic(marketUrl, nftTokenId);
 0378        }
 379        else
 380        {
 0381            Hide();
 382        }
 0383    }
 384
 385    void INFTPromptHUDView.OnError(string error)
 386    {
 0387        Debug.LogError(error);
 0388        ShowMainErrorFeedback(true);
 0389    }
 390
 391    private void OnDestroy()
 392    {
 7393        isDestroyed = true;
 394
 7395        multipleOwnersContainer.OnPointerEnter -= OwnerLabelPointerEnter;
 7396        multipleOwnersContainer.OnPointerExit -= OwnerLabelPointerExit;
 7397        ownersTooltip.OnViewAllPressed -= OnViewAllOwnersPressed;
 7398        ownersTooltip.OnFocusLost -= OnOwnersTooltipLostFocus;
 7399        ownersTooltip.OnFocus -= OnOwnersTooltipGainFocus;
 7400        ownersPopup.OnClosePopup -= OnOwnersPopupClose;
 401
 7402        ForgetPromises();
 7403    }
 404
 405    private void ForgetPromises()
 406    {
 8407        if (imagePromise != null)
 408        {
 0409            imagePromise.Forget();
 0410            imagePromise = null;
 411        }
 8412        gifPlayer?.Dispose();
 8413        gifPlayer = null;
 8414    }
 415
 416    private void SetupGifPlayer(Asset_Gif gif)
 417    {
 0418        if (gifPlayer == null)
 419        {
 0420            gifPlayer = new GifPlayer();
 0421            gifPlayer.OnFrameTextureChanged += (texture) => { imageNft.texture = texture; };
 422        }
 0423        gifPlayer.SetGif(gif);
 0424        gifPlayer.Play(true);
 0425    }
 426
 0427    private void OnViewAllOwnersPressed() { OnViewAllPressed?.Invoke(); }
 428
 0429    private void OnOwnersTooltipGainFocus() { OnOwnersTooltipFocus?.Invoke(); }
 430
 0431    private void OnOwnersTooltipLostFocus() { OnOwnersTooltipFocusLost?.Invoke(); }
 432
 0433    private void OnOwnersPopupClose() { OnOwnersPopupClosed?.Invoke(); }
 434
 0435    private void OwnerLabelPointerEnter() { OnOwnerLabelPointerEnter?.Invoke(); }
 436
 0437    private void OwnerLabelPointerExit() { OnOwnerLabelPointerExit?.Invoke(); }
 438
 439    private void ShowMainLoading(bool isVisible)
 440    {
 1441        if (spinnerGeneral == null)
 0442            return;
 443
 1444        spinnerGeneral.SetActive(isVisible);
 1445    }
 446
 447    private void ShowMainErrorFeedback(bool isVisible)
 448    {
 1449        if (mainErrorFeedbackContent == null)
 0450            return;
 451
 1452        if (isVisible)
 0453            ShowMainLoading(false);
 454
 1455        mainErrorFeedbackContent.SetActive(isVisible);
 1456    }
 457
 458    private void ShowImageLoading(bool isVisible)
 459    {
 1460        if (spinnerNftImage == null)
 0461            return;
 462
 1463        spinnerNftImage.SetActive(isVisible);
 1464    }
 465
 466    private void ShowImageErrorFeedback(bool isVisible)
 467    {
 0468        if (imageErrorFeedbackContent == null)
 0469            return;
 470
 0471        if (isVisible)
 0472            ShowImageLoading(false);
 473
 0474        imageErrorFeedbackContent.SetActive(isVisible);
 0475    }
 476}