< 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:37
Uncovered lines:46
Coverable lines:83
Total lines:185
Line coverage:44.5% (37 of 83)
Covered branches:0
Total branches:0
Covered methods:3
Total methods:7
Method coverage:42.8% (3 of 7)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
LoadNFTAsset()0%12300%
LoadNFTAsset()0%16.7114076%
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 Cysharp.Threading.Tasks;
 2using NFTShape_Internal;
 3using System;
 4using System.Collections;
 5using System.Collections.Generic;
 6using System.Threading;
 7using UnityEngine;
 8using UnityEngine.Networking;
 9
 10namespace DCL
 11{
 12    public interface INFTAssetRetriever : IDisposable
 13    {
 14        IEnumerator LoadNFTAsset(string url, Action<INFTAsset> OnSuccess, Action<Exception> OnFail);
 15        UniTask<INFTAsset> LoadNFTAsset(string url);
 16    }
 17
 18    public class NFTAssetRetriever : INFTAssetRetriever
 19    {
 20        private const string CONTENT_TYPE = "Content-Type";
 21        private const string CONTENT_LENGTH = "Content-Length";
 22        private const string CONTENT_TYPE_GIF = "image/gif";
 23        private const string CONTENT_TYPE_WEBP = "image/webp";
 24        private const long PREVIEW_IMAGE_SIZE_LIMIT = 6000000;
 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 = string.Equals(contentType, CONTENT_TYPE_GIF, StringComparison.InvariantCultureIgnoreCase);
 669            bool isWebp = string.Equals(contentType, CONTENT_TYPE_WEBP, StringComparison.InvariantCultureIgnoreCase);
 70
 671            if (isWebp)
 72            {
 73                // We are going to fallback into gifs until we have proper support
 074                yield return FetchGif(url + "&fm=gif",
 75                    OnSuccess: (promise) =>
 76                    {
 077                        UnloadPromises();
 078                        this.gifPromise = promise;
 079                        OnSuccess?.Invoke(new NFTAsset_Gif(promise.asset));
 080                    },
 081                    OnFail: (exception) => { OnFail?.Invoke(exception); }
 82                );
 83
 084                yield break;
 85            }
 686            if (isGif)
 87            {
 288                yield return FetchGif(url,
 89                    OnSuccess: (promise) =>
 90                    {
 291                        UnloadPromises();
 292                        this.gifPromise = promise;
 293                        OnSuccess?.Invoke(new NFTAsset_Gif(promise.asset));
 294                    },
 095                    OnFail: (exception) => { OnFail?.Invoke(exception); }
 96                );
 97
 298                yield break;
 99            }
 100
 4101            if (contentLength > PREVIEW_IMAGE_SIZE_LIMIT)
 102            {
 1103                OnFail?.Invoke(new Exception($"Image is too big! {contentLength} > {PREVIEW_IMAGE_SIZE_LIMIT}"));
 1104                yield break;
 105            }
 106
 3107            yield return FetchImage(url,
 108                OnSuccess: (promise) =>
 109                {
 3110                    UnloadPromises();
 3111                    this.imagePromise = promise;
 3112                    OnSuccess?.Invoke(new NFTAsset_Image(promise.asset));
 3113                },
 0114                OnFail: (exc) => { OnFail?.Invoke(exc); });
 3115        }
 116
 117        public void Dispose()
 118        {
 5119            UnloadPromises();
 5120            tokenSource?.Cancel();
 5121            tokenSource?.Dispose();
 0122        }
 123
 124        protected virtual IEnumerator GetHeaders(string url, HashSet<string> headerField,
 125            Action<Dictionary<string, string>> OnSuccess, Action<string> OnFail)
 126        {
 0127            using (var request = UnityWebRequest.Head(url))
 128            {
 0129                yield return request.SendWebRequest();
 130
 0131                if (request.WebRequestSucceded())
 132                {
 0133                    var result = new Dictionary<string, string>();
 134
 0135                    foreach (var key in headerField)
 136                    {
 0137                        result.Add(key, request.GetResponseHeader(key));
 138                    }
 139
 0140                    OnSuccess?.Invoke(result);
 141                }
 142                else
 143                {
 0144                    OnFail?.Invoke(request.error);
 145                }
 0146            }
 0147        }
 148
 149        protected virtual IEnumerator FetchGif(string url, Action<AssetPromise_Gif> OnSuccess,
 150            Action<Exception> OnFail = null)
 151        {
 0152            AssetPromise_Gif gifPromise = new AssetPromise_Gif(url);
 0153            gifPromise.OnSuccessEvent += texture => { OnSuccess?.Invoke(gifPromise); };
 0154            gifPromise.OnFailEvent += (x, error) => OnFail?.Invoke(error);
 155
 0156            AssetPromiseKeeper_Gif.i.Keep(gifPromise);
 157
 0158            yield return gifPromise;
 0159        }
 160
 161        protected virtual IEnumerator FetchImage(string url, Action<AssetPromise_Texture> OnSuccess,
 162            Action<Exception> OnFail = null)
 163        {
 0164            AssetPromise_Texture texturePromise = new AssetPromise_Texture(url);
 0165            texturePromise.OnSuccessEvent += texture => { OnSuccess?.Invoke(texturePromise); };
 0166            texturePromise.OnFailEvent += (x, error) => OnFail?.Invoke(error);
 167
 0168            AssetPromiseKeeper_Texture.i.Keep(texturePromise);
 169
 0170            yield return texturePromise;
 0171        }
 172
 173        protected virtual void UnloadPromises()
 174        {
 10175            if (gifPromise != null)
 2176                AssetPromiseKeeper_Gif.i.Forget(gifPromise);
 177
 10178            if (imagePromise != null)
 3179                AssetPromiseKeeper_Texture.i.Forget(imagePromise);
 180
 10181            gifPromise = null;
 10182            imagePromise = null;
 10183        }
 184    }
 185}