| | 1 | | using System; |
| | 2 | | using System.Collections; |
| | 3 | | using System.Collections.Generic; |
| | 4 | | using DCL.Helpers; |
| | 5 | | using NFTShape_Internal; |
| | 6 | | using UnityEngine; |
| | 7 | | using UnityEngine.Networking; |
| | 8 | |
|
| | 9 | | namespace DCL |
| | 10 | | { |
| | 11 | | public interface INFTAssetLoadHelper : IDisposable |
| | 12 | | { |
| | 13 | | IEnumerator LoadNFTAsset(string url, Action<INFTAsset> OnSuccess, Action<Exception> OnFail); |
| | 14 | | } |
| | 15 | |
|
| | 16 | | public class NFTAssetLoadHelper : INFTAssetLoadHelper |
| | 17 | | { |
| | 18 | | protected AssetPromise_Texture imagePromise = null; |
| | 19 | | protected AssetPromise_Gif gifPromise = null; |
| | 20 | |
|
| | 21 | | public IEnumerator LoadNFTAsset(string url, Action<INFTAsset> OnSuccess, Action<Exception> OnFail) |
| | 22 | | { |
| 6 | 23 | | if (string.IsNullOrEmpty(url)) |
| | 24 | | { |
| 0 | 25 | | OnFail?.Invoke(new Exception($"Image url is null!")); |
| 0 | 26 | | yield break; |
| | 27 | | } |
| | 28 | |
|
| | 29 | | const string CONTENT_TYPE = "Content-Type"; |
| | 30 | | const string CONTENT_LENGTH = "Content-Length"; |
| | 31 | | const string CONTENT_TYPE_GIF = "image/gif"; |
| | 32 | | const long PREVIEW_IMAGE_SIZE_LIMIT = 500000; |
| | 33 | |
|
| 6 | 34 | | HashSet<string> headers = new HashSet<string>() {CONTENT_TYPE, CONTENT_LENGTH}; |
| 6 | 35 | | Dictionary<string, string> responseHeaders = new Dictionary<string, string>(); |
| 6 | 36 | | string headerRequestError = string.Empty; |
| | 37 | |
|
| 12 | 38 | | yield return GetHeaders(url, headers, result => responseHeaders = result, (x) => headerRequestError = x); |
| | 39 | |
|
| 6 | 40 | | if (!string.IsNullOrEmpty(headerRequestError)) |
| | 41 | | { |
| 0 | 42 | | OnFail?.Invoke(new Exception($"Error fetching headers! ({headerRequestError})")); |
| 0 | 43 | | yield break; |
| | 44 | | } |
| | 45 | |
|
| 6 | 46 | | string contentType = responseHeaders[CONTENT_TYPE]; |
| 6 | 47 | | long.TryParse(responseHeaders[CONTENT_LENGTH], out long contentLength); |
| 6 | 48 | | bool isGif = contentType == CONTENT_TYPE_GIF; |
| | 49 | |
|
| 6 | 50 | | if (isGif) |
| | 51 | | { |
| 2 | 52 | | yield return FetchGif(url, |
| | 53 | | OnSuccess: (promise) => |
| | 54 | | { |
| 2 | 55 | | UnloadPromises(); |
| 2 | 56 | | this.gifPromise = promise; |
| 2 | 57 | | OnSuccess?.Invoke(new NFTAsset_Gif(promise.asset)); |
| 2 | 58 | | }, |
| 0 | 59 | | OnFail: (exception) => { OnFail?.Invoke(exception); } |
| | 60 | | ); |
| | 61 | |
|
| 2 | 62 | | yield break; |
| | 63 | | } |
| | 64 | |
|
| 4 | 65 | | if (contentLength > PREVIEW_IMAGE_SIZE_LIMIT) |
| | 66 | | { |
| 1 | 67 | | OnFail?.Invoke(new System.Exception($"Image is too big! {contentLength} > {PREVIEW_IMAGE_SIZE_LIMIT}")); |
| 1 | 68 | | yield break; |
| | 69 | | } |
| | 70 | |
|
| 3 | 71 | | yield return FetchImage(url, |
| | 72 | | OnSuccess: (promise) => |
| | 73 | | { |
| 3 | 74 | | UnloadPromises(); |
| 3 | 75 | | this.imagePromise = promise; |
| 3 | 76 | | OnSuccess?.Invoke(new NFTAsset_Image(promise.asset)); |
| 3 | 77 | | }, |
| 0 | 78 | | OnFail: (exc) => { OnFail?.Invoke(exc); }); |
| 3 | 79 | | } |
| | 80 | |
|
| | 81 | | public void Dispose() |
| | 82 | | { |
| 5 | 83 | | UnloadPromises(); |
| 5 | 84 | | } |
| | 85 | |
|
| | 86 | | protected virtual IEnumerator GetHeaders(string url, HashSet<string> headerField, |
| | 87 | | Action<Dictionary<string, string>> OnSuccess, Action<string> OnFail) |
| | 88 | | { |
| 0 | 89 | | using (var request = UnityWebRequest.Head(url)) |
| | 90 | | { |
| 0 | 91 | | yield return request.SendWebRequest(); |
| | 92 | |
|
| 0 | 93 | | if (request.WebRequestSucceded()) |
| | 94 | | { |
| 0 | 95 | | var result = new Dictionary<string, string>(); |
| | 96 | |
|
| 0 | 97 | | foreach (var key in headerField) |
| | 98 | | { |
| 0 | 99 | | result.Add(key, request.GetResponseHeader(key)); |
| | 100 | | } |
| | 101 | |
|
| 0 | 102 | | OnSuccess?.Invoke(result); |
| 0 | 103 | | } |
| | 104 | | else |
| | 105 | | { |
| 0 | 106 | | OnFail?.Invoke(request.error); |
| | 107 | | } |
| 0 | 108 | | } |
| 0 | 109 | | } |
| | 110 | |
|
| | 111 | | protected virtual IEnumerator FetchGif(string url, Action<AssetPromise_Gif> OnSuccess, |
| | 112 | | Action<Exception> OnFail = null) |
| | 113 | | { |
| 0 | 114 | | AssetPromise_Gif gifPromise = new AssetPromise_Gif(url); |
| 0 | 115 | | gifPromise.OnSuccessEvent += texture => { OnSuccess?.Invoke(gifPromise); }; |
| 0 | 116 | | gifPromise.OnFailEvent += (x, error) => OnFail?.Invoke(error); |
| | 117 | |
|
| 0 | 118 | | AssetPromiseKeeper_Gif.i.Keep(gifPromise); |
| | 119 | |
|
| 0 | 120 | | yield return gifPromise; |
| 0 | 121 | | } |
| | 122 | |
|
| | 123 | | protected virtual IEnumerator FetchImage(string url, Action<AssetPromise_Texture> OnSuccess, |
| | 124 | | Action<Exception> OnFail = null) |
| | 125 | | { |
| 0 | 126 | | AssetPromise_Texture texturePromise = new AssetPromise_Texture(url); |
| 0 | 127 | | texturePromise.OnSuccessEvent += texture => { OnSuccess?.Invoke(texturePromise); }; |
| 0 | 128 | | texturePromise.OnFailEvent += (x, error) => OnFail?.Invoke(error); |
| | 129 | |
|
| 0 | 130 | | AssetPromiseKeeper_Texture.i.Keep(texturePromise); |
| | 131 | |
|
| 0 | 132 | | yield return texturePromise; |
| 0 | 133 | | } |
| | 134 | |
|
| | 135 | | protected virtual void UnloadPromises() |
| | 136 | | { |
| 10 | 137 | | if (gifPromise != null) |
| 2 | 138 | | AssetPromiseKeeper_Gif.i.Forget(gifPromise); |
| | 139 | |
|
| 10 | 140 | | if (imagePromise != null) |
| 3 | 141 | | AssetPromiseKeeper_Texture.i.Forget(imagePromise); |
| | 142 | |
|
| 10 | 143 | | gifPromise = null; |
| 10 | 144 | | imagePromise = null; |
| 10 | 145 | | } |
| | 146 | | } |
| | 147 | | } |