| | 1 | | using Cysharp.Threading.Tasks; |
| | 2 | | using DCL.Tasks; |
| | 3 | | using DCLServices.WearablesCatalogService; |
| | 4 | | using System; |
| | 5 | | using System.Collections.Generic; |
| | 6 | | using System.Threading; |
| | 7 | | using UnityEngine; |
| | 8 | |
|
| | 9 | | namespace DCL.Backpack |
| | 10 | | { |
| | 11 | | public class BackpackFiltersController |
| | 12 | | { |
| | 13 | | private const string DECENTRALAND_COLLECTION_ID = "decentraland"; |
| | 14 | |
|
| | 15 | | public event Action<HashSet<string>> OnThirdPartyCollectionChanged; |
| | 16 | | public event Action<(NftOrderByOperation type, bool directionAscendent)> OnSortByChanged; |
| | 17 | | public event Action<string> OnSearchTextChanged; |
| | 18 | | public event Action<NftCollectionType> OnCollectionTypeChanged; |
| | 19 | |
|
| | 20 | | private readonly IBackpackFiltersComponentView view; |
| | 21 | | private readonly IWearablesCatalogService wearablesCatalogService; |
| | 22 | | private bool collectionsAlreadyLoaded; |
| 75 | 23 | | private HashSet<string> selectedCollections = new(); |
| 75 | 24 | | private HashSet<string> loadedCollections = new (); |
| 75 | 25 | | private NftCollectionType collectionType = NftCollectionType.OnChain | NftCollectionType.Base; |
| 75 | 26 | | private CancellationTokenSource loadThirdPartyCollectionsCancellationToken = new (); |
| | 27 | |
|
| 75 | 28 | | public BackpackFiltersController( |
| | 29 | | IBackpackFiltersComponentView view, |
| | 30 | | IWearablesCatalogService wearablesCatalogService) |
| | 31 | | { |
| 75 | 32 | | this.view = view; |
| 75 | 33 | | this.wearablesCatalogService = wearablesCatalogService; |
| | 34 | |
|
| 75 | 35 | | view.OnOnlyCollectiblesChanged += SetOnlyCollectibles; |
| 75 | 36 | | view.OnCollectionChanged += SetInternalStateOfCollectionsAndTriggerStateChange; |
| 75 | 37 | | view.OnSortByChanged += TriggerSorting; |
| 75 | 38 | | view.OnSearchTextChanged += TriggerTextSearch; |
| 75 | 39 | | } |
| | 40 | |
|
| | 41 | | public void Dispose() |
| | 42 | | { |
| 75 | 43 | | view.OnOnlyCollectiblesChanged -= SetOnlyCollectibles; |
| 75 | 44 | | view.OnCollectionChanged -= SetInternalStateOfCollectionsAndTriggerStateChange; |
| 75 | 45 | | view.OnSortByChanged -= TriggerSorting; |
| 75 | 46 | | view.OnSearchTextChanged -= TriggerTextSearch; |
| | 47 | |
|
| 75 | 48 | | view.Dispose(); |
| 75 | 49 | | } |
| | 50 | |
|
| | 51 | | public void LoadCollections() |
| | 52 | | { |
| 10 | 53 | | if (collectionsAlreadyLoaded) |
| 0 | 54 | | return; |
| | 55 | |
|
| | 56 | | async UniTaskVoid FetchTPWAndLoadDropdown(CancellationToken cancellationToken) |
| | 57 | | { |
| | 58 | | try |
| | 59 | | { |
| 10 | 60 | | WearableCollectionsAPIData.Collection[] collections = await wearablesCatalogService.GetThirdPartyCol |
| 10 | 61 | | WearableCollectionsAPIData.Collection defaultCollection = new () { urn = DECENTRALAND_COLLECTION_ID, |
| | 62 | |
|
| 10 | 63 | | loadedCollections.Clear(); |
| 10 | 64 | | loadedCollections.Add(defaultCollection.urn); |
| 10 | 65 | | if (collections != null) |
| | 66 | | { |
| 8 | 67 | | foreach (var collection in collections) |
| 3 | 68 | | loadedCollections.Add(collection.urn); |
| | 69 | | } |
| | 70 | |
|
| 10 | 71 | | view.LoadCollectionDropdown(collections, defaultCollection); |
| 10 | 72 | | collectionsAlreadyLoaded = true; |
| 10 | 73 | | } |
| 0 | 74 | | catch (OperationCanceledException) { } |
| 0 | 75 | | catch (Exception e) { Debug.LogException(e); } |
| 10 | 76 | | } |
| | 77 | |
|
| 10 | 78 | | loadThirdPartyCollectionsCancellationToken = loadThirdPartyCollectionsCancellationToken.SafeRestart(); |
| 10 | 79 | | FetchTPWAndLoadDropdown(loadThirdPartyCollectionsCancellationToken.Token).Forget(); |
| 10 | 80 | | } |
| | 81 | |
|
| | 82 | | public void ClearTextSearch(bool notify = true) => |
| 41 | 83 | | view.SetSearchText(null, notify); |
| | 84 | |
|
| | 85 | | public void SetTextSearch(string text, bool notify = true) => |
| 5 | 86 | | view.SetSearchText(text, notify); |
| | 87 | |
|
| | 88 | | public void SelectCollections(NftCollectionType collectionTypeMask, |
| | 89 | | ICollection<string> thirdPartyCollectionIdsFilter = null, |
| | 90 | | bool notify = true) |
| | 91 | | { |
| 46 | 92 | | HashSet<string> newSelectedCollections = new (); |
| | 93 | |
|
| 46 | 94 | | if ((collectionTypeMask & NftCollectionType.OnChain) != 0) |
| 46 | 95 | | newSelectedCollections.Add(DECENTRALAND_COLLECTION_ID); |
| | 96 | |
|
| 46 | 97 | | if ((collectionTypeMask & NftCollectionType.ThirdParty) != 0 && thirdPartyCollectionIdsFilter != null) |
| 8 | 98 | | foreach (string tpw in thirdPartyCollectionIdsFilter) |
| 3 | 99 | | newSelectedCollections.Add(tpw); |
| | 100 | |
|
| 46 | 101 | | bool isOnlyCollectiblesOn = (collectionTypeMask & NftCollectionType.Base) == 0; |
| 46 | 102 | | view.SetOnlyCollectiblesToggleIsOn(isOnlyCollectiblesOn, notify); |
| 46 | 103 | | view.SelectDropdownCollections(newSelectedCollections, notify); |
| | 104 | |
|
| 46 | 105 | | collectionType = collectionTypeMask; |
| 46 | 106 | | selectedCollections = newSelectedCollections; |
| 46 | 107 | | } |
| | 108 | |
|
| | 109 | | public void SetSorting(NftOrderByOperation type, bool directionAscending, bool notify) => |
| 23 | 110 | | view.SetSorting(type, directionAscending, notify); |
| | 111 | |
|
| | 112 | | private void SetOnlyCollectibles(bool isOn) |
| | 113 | | { |
| 2 | 114 | | if (isOn) |
| 1 | 115 | | collectionType &= ~NftCollectionType.Base; |
| | 116 | | else |
| 1 | 117 | | collectionType |= NftCollectionType.Base; |
| | 118 | |
|
| 2 | 119 | | OnCollectionTypeChanged?.Invoke(collectionType); |
| 2 | 120 | | } |
| | 121 | |
|
| | 122 | | private void SetInternalStateOfCollectionsAndTriggerStateChange(HashSet<string> newSelectedCollections) => |
| 2 | 123 | | SetInternalStateOfCollectionsAndTriggerStateChange(newSelectedCollections, true); |
| | 124 | |
|
| | 125 | | private void SetInternalStateOfCollectionsAndTriggerStateChange(HashSet<string> newSelectedCollections, bool not |
| | 126 | | { |
| 2 | 127 | | if (newSelectedCollections.Contains(DECENTRALAND_COLLECTION_ID)) |
| | 128 | | { |
| 1 | 129 | | collectionType |= NftCollectionType.OnChain; |
| 1 | 130 | | newSelectedCollections.Remove(DECENTRALAND_COLLECTION_ID); |
| | 131 | | } |
| | 132 | | else |
| 1 | 133 | | collectionType &= ~NftCollectionType.OnChain; |
| | 134 | |
|
| 2 | 135 | | selectedCollections = newSelectedCollections; |
| | 136 | |
|
| 2 | 137 | | if (newSelectedCollections.Count > 0) |
| 2 | 138 | | collectionType |= NftCollectionType.ThirdParty; |
| | 139 | | else |
| 0 | 140 | | collectionType &= ~NftCollectionType.ThirdParty; |
| | 141 | |
|
| 2 | 142 | | if (notify) |
| | 143 | | { |
| 2 | 144 | | OnCollectionTypeChanged?.Invoke(collectionType); |
| 2 | 145 | | OnThirdPartyCollectionChanged?.Invoke(selectedCollections); |
| | 146 | | } |
| 2 | 147 | | } |
| | 148 | |
|
| | 149 | | private void TriggerSorting((NftOrderByOperation type, bool directionAscendent) newSorting) => |
| 7 | 150 | | OnSortByChanged?.Invoke(newSorting); |
| | 151 | |
|
| | 152 | | private void TriggerTextSearch(string newText) => |
| 2 | 153 | | OnSearchTextChanged?.Invoke(newText); |
| | 154 | | } |
| | 155 | | } |