< 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:115
Coverable lines:188
Total lines:459
Line coverage:38.8% (73 of 188)
Covered branches:0
Total branches:0
Covered methods:15
Total methods:30
Method coverage:50% (15 of 30)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Awake()0%110100%
Dispose()0%4.134080%
Hide()0%4.034087.5%
GetOwnersPopup()0%110100%
GetOwnersTooltip()0%110100%
SetActive(...)0%110100%
IsActive()0%110100%
GetOwnerElementPrefab()0%110100%
SetLoading()0%22095.65%
SetNFTInfo(...)0%2401500%
Show()0%110100%
FetchNFTImage()0%30500%
UpdateTexture(...)0%2100%
SetNFTImageSize(...)0%6200%
ShortDecimals(...)0%30500%
SetTransparentBackground()0%110100%
SetTokenSymbol(...)0%2100%
OpenMarketUrl()0%6200%
OnError(...)0%2100%
OnDestroy()0%3.013090%
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 DCL;
 2using DCL.Helpers;
 3using DCL.Interface;
 4using MainScripts.DCL.ServiceProviders.OpenSea.Interfaces;
 5using NFTShape_Internal;
 6using System;
 7using System.Collections;
 8using TMPro;
 9using UnityEngine;
 10using UnityEngine.UI;
 11
 12internal interface INFTPromptHUDView : IDisposable
 13{
 14    event Action OnOwnerLabelPointerEnter;
 15    event Action OnOwnerLabelPointerExit;
 16    event Action OnOwnersTooltipFocusLost;
 17    event Action OnOwnersTooltipFocus;
 18    event Action OnViewAllPressed;
 19    event Action OnOwnersPopupClosed;
 20    void SetActive(bool active);
 21    bool IsActive();
 22    IOwnersTooltipView GetOwnersTooltip();
 23    IOwnersPopupView GetOwnersPopup();
 24    OwnerInfoElement GetOwnerElementPrefab();
 25    void SetLoading();
 26
 27    void SetNFTInfo(NFTInfo info, string comment);
 28    void OnError(string error);
 29}
 30
 31internal class NFTPromptHUDView : MonoBehaviour, INFTPromptHUDView
 32{
 33    private const string MULTIPLE_OWNERS_FORMAT = "{0} owners";
 34    private const int ADDRESS_MAX_CHARS = 11;
 35
 36    public event Action OnOwnerLabelPointerEnter;
 37    public event Action OnOwnerLabelPointerExit;
 38    public event Action OnOwnersTooltipFocusLost;
 39    public event Action OnOwnersTooltipFocus;
 40    public event Action OnViewAllPressed;
 41    public event Action OnOwnersPopupClosed;
 42
 43    [SerializeField] internal GameObject content;
 44    [SerializeField] internal GameObject nftContent;
 45    [SerializeField] internal GameObject mainErrorFeedbackContent;
 46    [SerializeField] internal GameObject imageErrorFeedbackContent;
 47
 48    [SerializeField] RawImage imageNft;
 49    [SerializeField] Image imageNftBackground;
 50    [SerializeField] TextMeshProUGUI textNftName;
 51    [SerializeField] TextMeshProUGUI textOwner;
 52    [SerializeField] TextMeshProUGUI textMultipleOwner;
 53    [SerializeField] UIHoverCallback multipleOwnersContainer;
 54
 55    [Header("Last Sale")] [SerializeField] TextMeshProUGUI textLastSaleSymbol;
 56    [SerializeField] TextMeshProUGUI textLastSalePrice;
 57    [SerializeField] TextMeshProUGUI textLastSaleNeverSold;
 58
 59    [Header("Price")] [SerializeField] TextMeshProUGUI textPriceSymbol;
 60    [SerializeField] TextMeshProUGUI textPrice;
 61    [SerializeField] TextMeshProUGUI textPriceNotForSale;
 62
 63    [Header("Description & Comment")]
 64    [SerializeField]
 65    TextMeshProUGUI textDescription;
 66
 67    [SerializeField] TextMeshProUGUI textComment;
 68    [SerializeField] GameObject containerDescription;
 69    [SerializeField] GameObject containerComment;
 70
 71    [Header("Spinners")] [SerializeField] GameObject spinnerGeneral;
 72    [SerializeField] GameObject spinnerNftImage;
 73
 74    [Header("Buttons")] [SerializeField] internal Button buttonClose;
 75    [SerializeField] internal Button buttonCancel;
 76    [SerializeField] internal Button buttonOpenMarket;
 77    [SerializeField] TextMeshProUGUI textOpenMarketButton;
 78
 79    [Header("Owners")]
 80    [SerializeField] internal OwnerInfoElement ownerElementPrefab;
 81    [SerializeField] internal OwnersTooltipView ownersTooltip;
 82    [SerializeField] internal OwnersPopupView ownersPopup;
 83
 84    Coroutine fetchNFTImageRoutine = null;
 85
 86    private string nftTokenId;
 87    bool backgroundColorSet = false;
 88    string marketUrl = null;
 89
 90    private bool isDestroyed = false;
 91    internal INFTAssetRetriever nftAssetRetriever;
 92    private INFTAsset nftAsset;
 93
 94    private void Awake()
 95    {
 896        name = "_NFTPromptHUD";
 97
 898        buttonClose.onClick.AddListener(Hide);
 899        buttonCancel.onClick.AddListener(Hide);
 8100        buttonOpenMarket.onClick.AddListener(OpenMarketUrl);
 101
 8102        multipleOwnersContainer.OnPointerEnter += OwnerLabelPointerEnter;
 8103        multipleOwnersContainer.OnPointerExit += OwnerLabelPointerExit;
 8104        ownersTooltip.OnViewAllPressed += OnViewAllOwnersPressed;
 8105        ownersTooltip.OnFocusLost += OnOwnersTooltipLostFocus;
 8106        ownersTooltip.OnFocus += OnOwnersTooltipGainFocus;
 8107        ownersPopup.OnClosePopup += OnOwnersPopupClose;
 8108    }
 109
 110    public void Dispose()
 111    {
 8112        if (!isDestroyed)
 113        {
 8114            Destroy(gameObject);
 115        }
 116
 8117        nftAssetRetriever?.Dispose();
 8118        nftAsset?.Dispose();
 0119    }
 120
 121    internal void Hide()
 122    {
 1123        content.SetActive(false);
 124
 1125        nftAssetRetriever?.Dispose();
 1126        nftAsset?.Dispose();
 127
 1128        if (fetchNFTImageRoutine != null)
 0129            StopCoroutine(fetchNFTImageRoutine);
 130
 1131        fetchNFTImageRoutine = null;
 132
 1133        AudioScriptableObjects.dialogClose.Play(true);
 1134    }
 135
 2136    IOwnersPopupView INFTPromptHUDView.GetOwnersPopup() { return ownersPopup; }
 137
 2138    IOwnersTooltipView INFTPromptHUDView.GetOwnersTooltip() { return ownersTooltip; }
 139
 18140    void INFTPromptHUDView.SetActive(bool active) { content.SetActive(active); }
 141
 2142    bool INFTPromptHUDView.IsActive() { return content.activeSelf; }
 143
 8144    OwnerInfoElement INFTPromptHUDView.GetOwnerElementPrefab() { return ownerElementPrefab; }
 145
 146    void INFTPromptHUDView.SetLoading()
 147    {
 2148        Show();
 149
 2150        if (fetchNFTImageRoutine != null)
 0151            StopCoroutine(fetchNFTImageRoutine);
 152
 2153        SetTransparentBackground();
 154
 2155        imageNft.gameObject.SetActive(false);
 2156        textNftName.gameObject.SetActive(false);
 2157        textOwner.gameObject.SetActive(false);
 2158        multipleOwnersContainer.gameObject.SetActive(false);
 2159        textLastSaleSymbol.gameObject.SetActive(false);
 2160        textLastSalePrice.gameObject.SetActive(false);
 2161        textLastSaleNeverSold.gameObject.SetActive(false);
 2162        textPriceSymbol.gameObject.SetActive(false);
 2163        textPrice.gameObject.SetActive(false);
 2164        textPriceNotForSale.gameObject.SetActive(false);
 2165        containerDescription.SetActive(false);
 2166        containerComment.SetActive(false);
 2167        buttonCancel.gameObject.SetActive(false);
 2168        buttonOpenMarket.gameObject.SetActive(false);
 169
 2170        nftContent.SetActive(false);
 2171        ShowImageLoading(false);
 2172        ShowMainLoading(true);
 2173        ShowMainErrorFeedback(false);
 2174    }
 175
 176    void INFTPromptHUDView.SetNFTInfo(NFTInfo info, string comment)
 177    {
 0178        Show();
 179
 0180        ShowMainLoading(false);
 0181        nftContent.SetActive(true);
 182
 0183        nftTokenId = info.tokenId;
 0184        SetTransparentBackground();
 0185        backgroundColorSet = info.backgroundColor != null;
 0186        if (backgroundColorSet)
 187        {
 0188            imageNftBackground.color = info.backgroundColor.Value;
 189        }
 190
 0191        textNftName.text = info.name;
 0192        textNftName.gameObject.SetActive(true);
 193
 0194        bool hasMultipleOwners = info.owners is { Length: > 1 };
 0195        if (hasMultipleOwners)
 196        {
 0197            textMultipleOwner.text = string.Format(MULTIPLE_OWNERS_FORMAT, info.owners.Length);
 198        }
 199        else
 200        {
 0201            textOwner.text = info.owners is { Length: 1 }
 202                ? NFTPromptHUDController.FormatOwnerAddress(info.owners[0].address, ADDRESS_MAX_CHARS)
 203                : NFTPromptHUDController.FormatOwnerAddress("0x0000000000000000000000000000000000000000", ADDRESS_MAX_CH
 204        }
 0205        textOwner.gameObject.SetActive(!hasMultipleOwners);
 0206        multipleOwnersContainer.gameObject.SetActive(hasMultipleOwners);
 207
 0208        if (!string.IsNullOrEmpty(info.lastSaleAmount))
 209        {
 0210            textLastSalePrice.text = ShortDecimals(info.lastSaleAmount, 4);
 0211            textLastSalePrice.gameObject.SetActive(true);
 212        }
 213        else
 214        {
 0215            textLastSaleNeverSold.gameObject.SetActive(true);
 216        }
 217
 0218        if (!string.IsNullOrEmpty(info.currentPrice))
 219        {
 0220            textPrice.text = ShortDecimals(info.currentPrice, 4);
 0221            textPrice.gameObject.SetActive(true);
 222
 0223            if (info.currentPriceToken != null)
 224            {
 0225                SetTokenSymbol(textPriceSymbol, info.currentPriceToken.Value.symbol);
 226            }
 227        }
 228        else
 229        {
 0230            textPriceNotForSale.gameObject.SetActive(true);
 231        }
 232
 0233        if (info.lastSaleToken != null)
 234        {
 0235            SetTokenSymbol(textLastSaleSymbol, info.lastSaleToken.Value.symbol);
 236        }
 237
 0238        if (!string.IsNullOrEmpty(info.description))
 239        {
 0240            textDescription.text = info.description;
 0241            containerDescription.SetActive(true);
 242        }
 243
 0244        if (!string.IsNullOrEmpty(comment))
 245        {
 0246            textComment.text = comment;
 0247            containerComment.SetActive(true);
 248        }
 249
 0250        textOpenMarketButton.text = "VIEW";
 0251        if (info.marketInfo != null)
 252        {
 0253            textOpenMarketButton.text = $"{textOpenMarketButton.text} ON {info.marketInfo.Value.name.ToUpper()}";
 254        }
 255
 0256        marketUrl = null;
 0257        if (!string.IsNullOrEmpty(info.marketLink))
 258        {
 0259            marketUrl = info.marketLink;
 260        }
 0261        else if (!string.IsNullOrEmpty(info.assetLink))
 262        {
 0263            marketUrl = info.assetLink;
 264        }
 265
 0266        buttonCancel.gameObject.SetActive(true);
 0267        buttonOpenMarket.gameObject.SetActive(true);
 268
 0269        fetchNFTImageRoutine = StartCoroutine(FetchNFTImage(info));
 0270    }
 271
 272    private void Show()
 273    {
 2274        content.SetActive(true);
 2275        Utils.UnlockCursor();
 2276    }
 277
 278    private IEnumerator FetchNFTImage(NFTInfo nftInfo)
 279    {
 0280        ShowImageErrorFeedback(false);
 0281        ShowImageLoading(true);
 282
 0283        nftAssetRetriever?.Dispose();
 0284        nftAsset?.Dispose();
 285
 0286        nftAssetRetriever = new NFTAssetRetriever();
 0287        yield return nftAssetRetriever.LoadNFTAsset(
 288            nftInfo.previewImageUrl,
 289            OnSuccess: nftAsset =>
 290            {
 0291                this.nftAsset = nftAsset;
 0292                nftAsset.OnTextureUpdate += UpdateTexture;
 293
 0294                if (!(nftAsset is Asset_Gif))
 295                {
 0296                    if (!backgroundColorSet)
 297                    {
 0298                        SetTransparentBackground();
 299                    }
 300                }
 301
 0302                UpdateTexture(nftAsset.previewAsset.texture);
 0303                SetNFTImageSize(nftAsset.previewAsset.texture);
 0304                imageNft.gameObject.SetActive(true);
 0305                ShowImageLoading(false);
 0306            },
 307            OnFail:
 0308            (exc) => { ShowImageErrorFeedback(true); });
 0309    }
 310
 311    private void UpdateTexture(Texture2D texture)
 312    {
 0313        imageNft.texture = texture;
 0314    }
 315
 316    private void SetNFTImageSize(Texture2D texture)
 317    {
 0318        RectTransform rt = (RectTransform)imageNft.transform.parent;
 319
 320        float h, w;
 321
 0322        if (texture.height > texture.width)
 323        {
 0324            h = rt.rect.height;
 0325            w = h * (texture.width / (float)texture.height);
 326        }
 327        else
 328        {
 0329            w = rt.rect.width;
 0330            h = w * (texture.height / (float)texture.width);
 331        }
 332
 0333        imageNft.rectTransform.sizeDelta = new Vector2(w, h);
 0334    }
 335
 336    private string ShortDecimals(string value, int decimalCount)
 337    {
 0338        int pointPosition = value.IndexOf('.');
 339
 0340        if (pointPosition <= 0)
 0341            return value;
 342
 0343        string ret = value.Substring(0, pointPosition + Mathf.Min(value.Length - pointPosition, decimalCount + 1));
 344
 0345        for (int i = ret.Length - 1; i >= 0; i--)
 346        {
 0347            if (ret[i] == '.')
 348            {
 0349                return ret.Substring(0, i);
 350            }
 351
 0352            if (ret[i] != '0')
 353            {
 0354                return ret.Substring(0, i + 1);
 355            }
 356        }
 357
 0358        return ret;
 359    }
 360
 361    private void SetTransparentBackground()
 362    {
 2363        imageNftBackground.color = new Color(
 364            imageNftBackground.color.r,
 365            imageNftBackground.color.g,
 366            imageNftBackground.color.b,
 367            0f);
 2368    }
 369
 370    private void SetTokenSymbol(TextMeshProUGUI textToken, string symbol)
 371    {
 0372        textToken.text = symbol;
 0373        textToken.gameObject.SetActive(true);
 0374    }
 375
 376    private void OpenMarketUrl()
 377    {
 0378        if (!string.IsNullOrEmpty(marketUrl))
 379        {
 0380            WebInterface.OpenURL(marketUrl);
 0381            AnalyticsHelper.SendExternalLinkAnalytic(marketUrl, nftTokenId);
 382        }
 383        else
 384        {
 0385            Hide();
 386        }
 0387    }
 388
 389    void INFTPromptHUDView.OnError(string error)
 390    {
 0391        Debug.LogError(error);
 0392        ShowMainErrorFeedback(true);
 0393    }
 394
 395    private void OnDestroy()
 396    {
 8397        isDestroyed = true;
 398
 8399        multipleOwnersContainer.OnPointerEnter -= OwnerLabelPointerEnter;
 8400        multipleOwnersContainer.OnPointerExit -= OwnerLabelPointerExit;
 8401        ownersTooltip.OnViewAllPressed -= OnViewAllOwnersPressed;
 8402        ownersTooltip.OnFocusLost -= OnOwnersTooltipLostFocus;
 8403        ownersTooltip.OnFocus -= OnOwnersTooltipGainFocus;
 8404        ownersPopup.OnClosePopup -= OnOwnersPopupClose;
 405
 8406        nftAssetRetriever?.Dispose();
 8407        nftAsset?.Dispose();
 0408    }
 409
 0410    private void OnViewAllOwnersPressed() { OnViewAllPressed?.Invoke(); }
 411
 0412    private void OnOwnersTooltipGainFocus() { OnOwnersTooltipFocus?.Invoke(); }
 413
 0414    private void OnOwnersTooltipLostFocus() { OnOwnersTooltipFocusLost?.Invoke(); }
 415
 0416    private void OnOwnersPopupClose() { OnOwnersPopupClosed?.Invoke(); }
 417
 0418    private void OwnerLabelPointerEnter() { OnOwnerLabelPointerEnter?.Invoke(); }
 419
 0420    private void OwnerLabelPointerExit() { OnOwnerLabelPointerExit?.Invoke(); }
 421
 422    private void ShowMainLoading(bool isVisible)
 423    {
 2424        if (spinnerGeneral == null)
 0425            return;
 426
 2427        spinnerGeneral.SetActive(isVisible);
 2428    }
 429
 430    private void ShowMainErrorFeedback(bool isVisible)
 431    {
 2432        if (mainErrorFeedbackContent == null)
 0433            return;
 434
 2435        if (isVisible)
 0436            ShowMainLoading(false);
 437
 2438        mainErrorFeedbackContent.SetActive(isVisible);
 2439    }
 440
 441    private void ShowImageLoading(bool isVisible)
 442    {
 2443        if (spinnerNftImage == null)
 0444            return;
 445
 2446        spinnerNftImage.SetActive(isVisible);
 2447    }
 448
 449    private void ShowImageErrorFeedback(bool isVisible)
 450    {
 0451        if (imageErrorFeedbackContent == null)
 0452            return;
 453
 0454        if (isVisible)
 0455            ShowImageLoading(false);
 456
 0457        imageErrorFeedbackContent.SetActive(isVisible);
 0458    }
 459}