< Summary

Class:DCL.NFTAssetRetriever
Assembly:DCL.Components.NFT
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/LoadableShapes/NFTShape/NFTAsset/NFTAssetLoadHelper.cs
Covered lines:35
Uncovered lines:40
Coverable lines:75
Total lines:169
Line coverage:46.6% (35 of 75)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
LoadNFTAsset()0%12300%
LoadNFTAsset()0%1312080.95%
Dispose()0%3.143075%
GetHeaders()0%56700%
FetchGif()0%12300%
FetchImage()0%12300%
UnloadPromises()0%330100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/LoadableShapes/NFTShape/NFTAsset/NFTAssetLoadHelper.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using System.Collections.Generic;
 4using System.Threading;
 5using Cysharp.Threading.Tasks;
 6using DCL.Helpers;
 7using NFTShape_Internal;
 8using UnityEngine;
 9using UnityEngine.Networking;
 10
 11namespace DCL
 12{
 13    public interface INFTAssetRetriever : IDisposable
 14    {
 15        IEnumerator LoadNFTAsset(string url, Action<INFTAsset> OnSuccess, Action<Exception> OnFail);
 16        UniTask<INFTAsset> LoadNFTAsset(string url);
 17    }
 18
 19    public class NFTAssetRetriever : INFTAssetRetriever
 20    {
 21        private const string CONTENT_TYPE = "Content-Type";
 22        private const string CONTENT_LENGTH = "Content-Length";
 23        private const string CONTENT_TYPE_GIF = "image/gif";
 24        private const long PREVIEW_IMAGE_SIZE_LIMIT = 500000;
 25
 26        protected AssetPromise_Texture imagePromise = null;
 27        protected AssetPromise_Gif gifPromise = null;
 28        private CancellationTokenSource tokenSource;
 29
 30        public async UniTask<INFTAsset> LoadNFTAsset(string url)
 31        {
 032            tokenSource = new CancellationTokenSource();
 033            tokenSource.Token.ThrowIfCancellationRequested();
 034            INFTAsset result = null;
 035            await LoadNFTAsset(url, (nftAsset) =>
 36            {
 037                result = nftAsset;
 038            }, (exception) =>
 39            {
 040                Debug.Log("Fail to load nft " + url + " due to " + exception.Message);
 041            }).WithCancellation(tokenSource.Token);
 42
 043            return result;
 044        }
 45
 46        public IEnumerator LoadNFTAsset(string url, Action<INFTAsset> OnSuccess, Action<Exception> OnFail)
 47        {
 648            if (string.IsNullOrEmpty(url))
 49            {
 050                OnFail?.Invoke(new Exception($"Image url is null!"));
 051                yield break;
 52            }
 53
 654            HashSet<string> headers = new HashSet<string>() {CONTENT_TYPE, CONTENT_LENGTH};
 655            Dictionary<string, string> responseHeaders = new Dictionary<string, string>();
 656            string headerRequestError = string.Empty;
 57
 1258            yield return GetHeaders(url, headers, result => responseHeaders = result, (x) => headerRequestError = x);
 59
 660            if (!string.IsNullOrEmpty(headerRequestError))
 61            {
 062                OnFail?.Invoke(new Exception($"Error fetching headers! ({headerRequestError})"));
 063                yield break;
 64            }
 65
 666            string contentType = responseHeaders[CONTENT_TYPE];
 667            long.TryParse(responseHeaders[CONTENT_LENGTH], out long contentLength);
 668            bool isGif = contentType == CONTENT_TYPE_GIF;
 69
 670            if (isGif)
 71            {
 272                yield return FetchGif(url,
 73                    OnSuccess: (promise) =>
 74                    {
 275                        UnloadPromises();
 276                        this.gifPromise = promise;
 277                        OnSuccess?.Invoke(new NFTAsset_Gif(promise.asset));
 278                    },
 079                    OnFail: (exception) => { OnFail?.Invoke(exception); }
 80                );
 81
 282                yield break;
 83            }
 84
 485            if (contentLength > PREVIEW_IMAGE_SIZE_LIMIT)
 86            {
 187                OnFail?.Invoke(new System.Exception($"Image is too big! {contentLength} > {PREVIEW_IMAGE_SIZE_LIMIT}"));
 188                yield break;
 89            }
 90
 391            yield return FetchImage(url,
 92                OnSuccess: (promise) =>
 93                {
 394                    UnloadPromises();
 395                    this.imagePromise = promise;
 396                    OnSuccess?.Invoke(new NFTAsset_Image(promise.asset));
 397                },
 098                OnFail: (exc) => { OnFail?.Invoke(exc); });
 399        }
 100
 101        public void Dispose()
 102        {
 14103            UnloadPromises();
 14104            tokenSource?.Cancel();
 14105            tokenSource?.Dispose();
 0106        }
 107
 108        protected virtual IEnumerator GetHeaders(string url, HashSet<string> headerField,
 109            Action<Dictionary<string, string>> OnSuccess, Action<string> OnFail)
 110        {
 0111            using (var request = UnityWebRequest.Head(url))
 112            {
 0113                yield return request.SendWebRequest();
 114
 0115                if (request.WebRequestSucceded())
 116                {
 0117                    var result = new Dictionary<string, string>();
 118
 0119                    foreach (var key in headerField)
 120                    {
 0121                        result.Add(key, request.GetResponseHeader(key));
 122                    }
 123
 0124                    OnSuccess?.Invoke(result);
 0125                }
 126                else
 127                {
 0128                    OnFail?.Invoke(request.error);
 129                }
 0130            }
 0131        }
 132
 133        protected virtual IEnumerator FetchGif(string url, Action<AssetPromise_Gif> OnSuccess,
 134            Action<Exception> OnFail = null)
 135        {
 0136            AssetPromise_Gif gifPromise = new AssetPromise_Gif(url);
 0137            gifPromise.OnSuccessEvent += texture => { OnSuccess?.Invoke(gifPromise); };
 0138            gifPromise.OnFailEvent += (x, error) => OnFail?.Invoke(error);
 139
 0140            AssetPromiseKeeper_Gif.i.Keep(gifPromise);
 141
 0142            yield return gifPromise;
 0143        }
 144
 145        protected virtual IEnumerator FetchImage(string url, Action<AssetPromise_Texture> OnSuccess,
 146            Action<Exception> OnFail = null)
 147        {
 0148            AssetPromise_Texture texturePromise = new AssetPromise_Texture(url);
 0149            texturePromise.OnSuccessEvent += texture => { OnSuccess?.Invoke(texturePromise); };
 0150            texturePromise.OnFailEvent += (x, error) => OnFail?.Invoke(error);
 151
 0152            AssetPromiseKeeper_Texture.i.Keep(texturePromise);
 153
 0154            yield return texturePromise;
 0155        }
 156
 157        protected virtual void UnloadPromises()
 158        {
 19159            if (gifPromise != null)
 2160                AssetPromiseKeeper_Gif.i.Forget(gifPromise);
 161
 19162            if (imagePromise != null)
 3163                AssetPromiseKeeper_Texture.i.Forget(imagePromise);
 164
 19165            gifPromise = null;
 19166            imagePromise = null;
 19167        }
 168    }
 169}