< Summary

Class:DCL.Backpack.WearableGridController
Assembly:BackpackEditorHUDV2
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/WearableGridController.cs
Covered lines:242
Uncovered lines:28
Coverable lines:270
Total lines:598
Line coverage:89.6% (242 of 270)
Covered branches:0
Total branches:0
Covered methods:34
Total methods:36
Method coverage:94.4% (34 of 36)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
WearableGridController(...)0%110100%
Dispose()0%110100%
LoadWearables()0%110100%
LoadWearablesWithFilters(...)0%110100%
CancelWearableLoading()0%110100%
Equip(...)0%220100%
UnEquip(...)0%220100%
UpdateBodyShapeCompatibility(...)0%330100%
LoadCollections()0%110100%
ResetFilters()0%110100%
ShowWearablesAndUpdateFilters()0%9.049092.31%
HandleNewPageRequested(...)0%110100%
RequestWearablesAndShowThem()0%34.7515055.56%
MergeCustomWearableItems()0%5.673033.33%
MergePublishedWearableCollections()0%5.673033.33%
MergeToWearableResults()0%6.066088.24%
MergeBuilderWearableCollections()0%5.095084.62%
FetchCustomWearableItems()0%20.027035.71%
FetchPublishedWearableCollections()0%10.899071.43%
FetchBuilderWearableCollections()0%10.549073.33%
ToWearableGridModel(...)0%6.325062.5%
IsEquipped(...)0%220100%
HandleWearableSelected(...)0%7.297081.82%
HandleWearableUnequipped(...)0%220100%
HandleWearableEquipped(...)0%220100%
FilterWearablesFromReferencePath(...)0%440100%
RemoveFiltersFromReferencePath(...)0%330100%
GoToMarketplace()0%330100%
SetThirdPartCollectionIds(...)0%2100%
SetSorting(...)0%110100%
SetNameFilterFromSearchText(...)0%220100%
SetCollectionTypeFromFilterSelection(...)0%2100%
SetCategoryFromFilterSelection(...)0%110100%
SetCategory(...)0%330100%
ThrottleLoadWearablesWithCurrentFilters()0%330100%
IsCompatibleWithBodyShape(...)0%330100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/BackpackEditorHUDV2/WearableGridController.cs

#LineLine coverage
 1using Cysharp.Threading.Tasks;
 2using DCL.Browser;
 3using DCL.Helpers;
 4using DCL.Tasks;
 5using DCLServices.CustomNftCollection;
 6using DCLServices.WearablesCatalogService;
 7using MainScripts.DCL.Controllers.HUD.CharacterPreview;
 8using System;
 9using System.Collections.Generic;
 10using System.Linq;
 11using System.Threading;
 12using System.Threading.Tasks;
 13using UnityEngine;
 14using UnityEngine.Pool;
 15
 16namespace DCL.Backpack
 17{
 18    public class WearableGridController
 19    {
 20        private const int PAGE_SIZE = 15;
 21        private const string ALL_FILTER_REF = "all";
 22        private const string NAME_FILTER_REF = "name=";
 23        private const string CATEGORY_FILTER_REF = "category=";
 24        private const string URL_MARKET_PLACE = "https://market.decentraland.org/browse?section=wearables";
 25        private const string URL_GET_A_WALLET = "https://docs.decentraland.org/get-a-wallet";
 26        private const string EMPTY_WEARABLE_DESCRIPTION = "This item doesn’t have a description.";
 27
 28        private readonly IWearableGridView view;
 29        private readonly IUserProfileBridge userProfileBridge;
 30        private readonly IWearablesCatalogService wearablesCatalogService;
 31        private readonly DataStore_BackpackV2 dataStoreBackpackV2;
 32        private readonly IBrowserBridge browserBridge;
 33        private readonly BackpackFiltersController backpackFiltersController;
 34        private readonly AvatarSlotsHUDController avatarSlotsHUDController;
 35        private readonly IBackpackAnalyticsService backpackAnalyticsService;
 36        private readonly ICustomNftCollectionService customNftCollectionService;
 6337        private readonly List<WearableItem> customWearablesBuffer = new ();
 38
 6339        private Dictionary<string, WearableGridItemModel> currentWearables = new ();
 6340        private CancellationTokenSource requestWearablesCancellationToken = new ();
 6341        private CancellationTokenSource filtersCancellationToken = new ();
 42        private string categoryFilter;
 43        private ICollection<string> thirdPartyCollectionIdsFilter;
 44        private string nameFilter;
 45
 46        // initialize as "newest"
 6347        private (NftOrderByOperation type, bool directionAscendent)? wearableSorting = new (NftOrderByOperation.Date, fa
 6348        private NftCollectionType collectionTypeMask = NftCollectionType.Base | NftCollectionType.OnChain;
 49
 50        public event Action<string> OnWearableSelected;
 51        public event Action<string, EquipWearableSource> OnWearableEquipped;
 52        public event Action<string, UnequipWearableSource> OnWearableUnequipped;
 53        public event Action OnCategoryFilterRemoved;
 54
 6355        public WearableGridController(IWearableGridView view,
 56            IUserProfileBridge userProfileBridge,
 57            IWearablesCatalogService wearablesCatalogService,
 58            DataStore_BackpackV2 dataStoreBackpackV2,
 59            IBrowserBridge browserBridge,
 60            BackpackFiltersController backpackFiltersController,
 61            AvatarSlotsHUDController avatarSlotsHUDController,
 62            IBackpackAnalyticsService backpackAnalyticsService,
 63            ICustomNftCollectionService customNftCollectionService)
 64        {
 6365            this.view = view;
 6366            this.userProfileBridge = userProfileBridge;
 6367            this.wearablesCatalogService = wearablesCatalogService;
 6368            this.dataStoreBackpackV2 = dataStoreBackpackV2;
 6369            this.browserBridge = browserBridge;
 6370            this.backpackFiltersController = backpackFiltersController;
 6371            this.avatarSlotsHUDController = avatarSlotsHUDController;
 6372            this.backpackAnalyticsService = backpackAnalyticsService;
 6373            this.customNftCollectionService = customNftCollectionService;
 74
 6375            view.OnWearablePageChanged += HandleNewPageRequested;
 6376            view.OnWearableEquipped += HandleWearableEquipped;
 6377            view.OnWearableUnequipped += HandleWearableUnequipped;
 6378            view.OnWearableSelected += HandleWearableSelected;
 6379            view.OnFilterSelected += FilterWearablesFromReferencePath;
 6380            view.OnFilterRemoved += RemoveFiltersFromReferencePath;
 6381            view.OnGoToMarketplace += GoToMarketplace;
 82
 6383            backpackFiltersController.OnThirdPartyCollectionChanged += SetThirdPartCollectionIds;
 6384            backpackFiltersController.OnSortByChanged += SetSorting;
 6385            backpackFiltersController.OnSearchTextChanged += SetNameFilterFromSearchText;
 6386            backpackFiltersController.OnCollectionTypeChanged += SetCollectionTypeFromFilterSelection;
 87
 6388            avatarSlotsHUDController.OnToggleSlot += SetCategoryFromFilterSelection;
 6389        }
 90
 91        public void Dispose()
 92        {
 6393            view.OnWearablePageChanged -= HandleNewPageRequested;
 6394            view.OnWearableEquipped -= HandleWearableEquipped;
 6395            view.OnWearableUnequipped -= HandleWearableUnequipped;
 6396            view.OnWearableSelected -= HandleWearableSelected;
 6397            view.OnFilterRemoved -= RemoveFiltersFromReferencePath;
 6398            view.OnFilterSelected -= FilterWearablesFromReferencePath;
 6399            view.OnGoToMarketplace -= GoToMarketplace;
 100
 63101            backpackFiltersController.OnThirdPartyCollectionChanged -= SetThirdPartCollectionIds;
 63102            backpackFiltersController.OnSortByChanged -= SetSorting;
 63103            backpackFiltersController.OnSearchTextChanged -= SetNameFilterFromSearchText;
 63104            backpackFiltersController.OnCollectionTypeChanged -= SetCollectionTypeFromFilterSelection;
 63105            backpackFiltersController.Dispose();
 106
 63107            avatarSlotsHUDController.OnToggleSlot -= SetCategoryFromFilterSelection;
 63108            avatarSlotsHUDController.Dispose();
 109
 63110            view.Dispose();
 63111            requestWearablesCancellationToken.SafeCancelAndDispose();
 63112            filtersCancellationToken.SafeCancelAndDispose();
 63113        }
 114
 115        public void LoadWearables()
 116        {
 14117            LoadWearablesWithFilters(categoryFilter, collectionTypeMask, thirdPartyCollectionIdsFilter,
 118                nameFilter, wearableSorting);
 14119        }
 120
 121        public void LoadWearablesWithFilters(string categoryFilter = null,
 122            NftCollectionType collectionTypeMask = NftCollectionType.All,
 123            ICollection<string> thirdPartyCollectionIdsFilter = null, string nameFilter = null,
 124            (NftOrderByOperation type, bool directionAscendent)? wearableSorting = null)
 125        {
 38126            this.categoryFilter = categoryFilter;
 38127            this.collectionTypeMask = collectionTypeMask;
 38128            this.thirdPartyCollectionIdsFilter = thirdPartyCollectionIdsFilter;
 38129            this.nameFilter = nameFilter;
 38130            this.wearableSorting = wearableSorting;
 38131            requestWearablesCancellationToken = requestWearablesCancellationToken.SafeRestart();
 38132            ShowWearablesAndUpdateFilters(1, requestWearablesCancellationToken.Token).Forget();
 38133        }
 134
 135        public void CancelWearableLoading() =>
 30136            requestWearablesCancellationToken.SafeCancelAndDispose();
 137
 138        public void Equip(string wearableId)
 139        {
 29140            if (!currentWearables.TryGetValue(wearableId, out WearableGridItemModel wearableGridModel))
 28141                return;
 142
 1143            wearableGridModel.IsEquipped = true;
 1144            view.SetWearable(wearableGridModel);
 1145            view.RefreshAllWearables();
 1146        }
 147
 148        public void UnEquip(string wearableId)
 149        {
 9150            if (!currentWearables.TryGetValue(wearableId, out WearableGridItemModel wearableGridModel))
 8151                return;
 152
 1153            wearableGridModel.IsEquipped = false;
 1154            view.SetWearable(wearableGridModel);
 1155            view.RefreshWearable(wearableId);
 1156        }
 157
 158        public void UpdateBodyShapeCompatibility(string bodyShapeId)
 159        {
 20160            foreach ((string wearableId, WearableGridItemModel model) in currentWearables)
 161            {
 2162                if (!wearablesCatalogService.WearablesCatalog.TryGetValue(wearableId, out WearableItem wearable)) contin
 2163                bool isCompatibleWithBodyShape = IsCompatibleWithBodyShape(bodyShapeId, wearable);
 2164                model.IsCompatibleWithBodyShape = isCompatibleWithBodyShape;
 2165                view.SetWearable(model);
 166            }
 8167        }
 168
 169        public void LoadCollections() =>
 9170            backpackFiltersController.LoadCollections();
 171
 172        public void ResetFilters()
 173        {
 30174            categoryFilter = null;
 30175            collectionTypeMask = NftCollectionType.Base | NftCollectionType.OnChain;
 30176            thirdPartyCollectionIdsFilter = null;
 30177            nameFilter = null;
 30178            wearableSorting = new (NftOrderByOperation.Date, false);
 30179        }
 180
 181        private async UniTaskVoid ShowWearablesAndUpdateFilters(int page, CancellationToken cancellationToken)
 182        {
 46183            List<(string reference, string name, string type, bool removable)> path = new ();
 184
 46185            var additiveReferencePath = $"{ALL_FILTER_REF}";
 46186            path.Add((reference: additiveReferencePath, name: "All", type: "all", removable: false));
 187
 46188            if (!string.IsNullOrEmpty(categoryFilter))
 189            {
 6190                additiveReferencePath += $"&{CATEGORY_FILTER_REF}{categoryFilter}";
 191
 192                // TODO: translate category id into names (??)
 6193                path.Add((reference: additiveReferencePath, name: categoryFilter, type: categoryFilter, removable: true)
 194            }
 195
 46196            if (!string.IsNullOrEmpty(nameFilter))
 197            {
 5198                additiveReferencePath += $"&{NAME_FILTER_REF}{nameFilter}";
 5199                path.Add((reference: additiveReferencePath, name: nameFilter, type: "nft-name", removable: true));
 200            }
 201
 46202            var wearableBreadcrumbModel = new NftBreadcrumbModel
 203            {
 204                Path = path.ToArray(),
 205                Current = path.Count - 1,
 206                ResultCount = 0,
 207            };
 208
 46209            view.SetWearableBreadcrumb(wearableBreadcrumbModel);
 210
 46211            if (string.IsNullOrEmpty(categoryFilter))
 212            {
 40213                avatarSlotsHUDController.ClearSlotSelection();
 40214                OnCategoryFilterRemoved?.Invoke();
 215            }
 216            else
 6217                avatarSlotsHUDController.SelectSlot(categoryFilter, false);
 218
 46219            if (string.IsNullOrEmpty(nameFilter))
 41220                backpackFiltersController.ClearTextSearch(false);
 221            else
 5222                backpackFiltersController.SetTextSearch(nameFilter, false);
 223
 46224            if (wearableSorting != null)
 225            {
 23226                (NftOrderByOperation type, bool directionAscending) = wearableSorting.Value;
 23227                backpackFiltersController.SetSorting(type, directionAscending, false);
 228            }
 229
 46230            backpackFiltersController.SelectCollections(collectionTypeMask, thirdPartyCollectionIdsFilter, false);
 231
 46232            int resultCount = await RequestWearablesAndShowThem(page, cancellationToken);
 233
 234            // This call has been removed to avoid flickering. The result count is hidden in the view
 235            // view.SetWearableBreadcrumb(wearableBreadcrumbModel with { ResultCount = resultCount });
 46236        }
 237
 238        private void HandleNewPageRequested(int page)
 239        {
 1240            requestWearablesCancellationToken = requestWearablesCancellationToken.SafeRestart();
 1241            RequestWearablesAndShowThem(page, requestWearablesCancellationToken.Token).Forget();
 1242        }
 243
 244        private async UniTask<int> RequestWearablesAndShowThem(int page, CancellationToken cancellationToken)
 245        {
 47246            AudioScriptableObjects.listItemAppear.ResetPitch();
 47247            UserProfile ownUserProfile = userProfileBridge.GetOwn();
 47248            string ownUserId = ownUserProfile.userId;
 249
 250            try
 251            {
 47252                currentWearables.Clear();
 253
 47254                view.SetLoadingActive(true);
 255
 47256                List<WearableItem> wearables = new ();
 257
 47258                (IReadOnlyList<WearableItem> ownedWearables, int totalAmount) = await wearablesCatalogService.RequestOwn
 259                    ownUserId,
 260                    page,
 261                    PAGE_SIZE, cancellationToken,
 262                    categoryFilter, NftRarity.None, collectionTypeMask,
 263                    thirdPartyCollectionIdsFilter,
 264                    nameFilter, wearableSorting);
 265
 47266                wearables.AddRange(ownedWearables);
 267
 268                try
 269                {
 47270                    totalAmount += await MergePublishedWearableCollections(page, wearables, totalAmount, cancellationTok
 47271                    totalAmount += await MergeBuilderWearableCollections(page, wearables, totalAmount, cancellationToken
 47272                    totalAmount += await MergeCustomWearableItems(page, wearables, totalAmount, cancellationToken);
 273
 47274                    customWearablesBuffer.Clear();
 47275                }
 0276                catch (Exception e) when (e is not OperationCanceledException) { Debug.LogError(e); }
 277
 47278                view.SetLoadingActive(false);
 279
 47280                currentWearables = wearables.Select(ToWearableGridModel)
 42281                                            .ToDictionary(item => ExtendedUrnParser.GetShortenedUrn(item.WearableId), mo
 282
 47283                view.SetWearablePages(page, Mathf.CeilToInt((float)totalAmount / PAGE_SIZE));
 284
 285                // TODO: mark the wearables to be disposed if no references left
 47286                view.ClearWearables();
 47287                view.ShowWearables(currentWearables.Values);
 288
 47289                return totalAmount;
 290            }
 0291            catch (OperationCanceledException) { }
 0292            catch (Exception e) { Debug.LogException(e); }
 293
 0294            return 0;
 47295        }
 296
 297        private async UniTask<int> MergeCustomWearableItems(int page, List<WearableItem> wearables,
 298            int totalAmount, CancellationToken cancellationToken) =>
 47299            await MergeToWearableResults(page, wearables, totalAmount, FetchCustomWearableItems, cancellationToken);
 300
 301        private async UniTask<int> MergePublishedWearableCollections(int page, List<WearableItem> wearables, int totalAm
 302            CancellationToken cancellationToken) =>
 47303             await MergeToWearableResults(page, wearables, totalAmount, FetchPublishedWearableCollections, cancellationT
 304
 305        private async UniTask<int> MergeToWearableResults(int page, List<WearableItem> wearables, int totalAmount,
 306            Func<List<WearableItem>, CancellationToken, UniTask> fetchOperation,
 307            CancellationToken cancellationToken)
 308        {
 94309            int startingPage = (totalAmount / PAGE_SIZE) + 1;
 94310            int pageOffset = page - startingPage;
 94311            int pageSize = PAGE_SIZE - wearables.Count;
 94312            int skip = pageOffset * PAGE_SIZE;
 94313            int until = skip + pageSize;
 314
 94315            customWearablesBuffer.Clear();
 316
 94317            await fetchOperation.Invoke(customWearablesBuffer, cancellationToken);
 318
 106319            if (skip < 0) return customWearablesBuffer.Count;
 320
 166321            for (int i = skip; i < customWearablesBuffer.Count && i < until; i++)
 1322                wearables.Add(customWearablesBuffer[i]);
 323
 82324            return customWearablesBuffer.Count;
 94325        }
 326
 327        private async UniTask<int> MergeBuilderWearableCollections(int page, List<WearableItem> wearables, int totalAmou
 328        {
 47329            int startingPage = (totalAmount / PAGE_SIZE) + 1;
 47330            int pageOffset = Mathf.Max(1, page - startingPage);
 47331            int pageSize = PAGE_SIZE - wearables.Count;
 332
 47333            customWearablesBuffer.Clear();
 334
 47335            int collectionsWearableCount = await FetchBuilderWearableCollections(pageOffset, PAGE_SIZE,
 336                customWearablesBuffer, cancellationToken);
 337
 96338            for (var i = 0; i < pageSize && i < customWearablesBuffer.Count; i++)
 1339                wearables.Add(customWearablesBuffer[i]);
 340
 47341            return collectionsWearableCount;
 47342        }
 343
 344        private async UniTask FetchCustomWearableItems(ICollection<WearableItem> wearables, CancellationToken cancellati
 345        {
 47346            IReadOnlyList<string> customItems = await customNftCollectionService.GetConfiguredCustomNftItemsAsync(cancel
 347
 47348            WearableItem[] retrievedWearables = await UniTask.WhenAll(customItems.Select(nftId =>
 349            {
 0350                if (nftId.StartsWith("urn", StringComparison.OrdinalIgnoreCase))
 0351                    return wearablesCatalogService.RequestWearableAsync(nftId, cancellationToken);
 352
 0353                return wearablesCatalogService.RequestWearableFromBuilderAsync(nftId, cancellationToken);
 354            }));
 355
 94356            foreach (WearableItem wearable in retrievedWearables)
 357            {
 0358                if (wearable == null)
 359                {
 0360                    Debug.LogWarning("Custom wearable item skipped is null");
 0361                    continue;
 362                }
 363
 0364                wearables.Add(wearable);
 365            }
 47366        }
 367
 368        private async UniTask FetchPublishedWearableCollections(
 369            List<WearableItem> wearableBuffer, CancellationToken cancellationToken)
 370        {
 47371            IReadOnlyList<string> customCollections =
 372                await customNftCollectionService.GetConfiguredCustomNftCollectionAsync(cancellationToken);
 373
 47374            HashSet<string> collectionsToRequest = HashSetPool<string>.Get();
 375
 98376            foreach (string collectionId in customCollections)
 2377                if (collectionId.StartsWith("urn", StringComparison.OrdinalIgnoreCase))
 1378                    collectionsToRequest.Add(collectionId);
 379
 47380            await wearablesCatalogService.RequestWearableCollection(collectionsToRequest, cancellationToken, wearableBuf
 381
 47382            HashSetPool<string>.Release(collectionsToRequest);
 47383        }
 384
 385        private async UniTask<int> FetchBuilderWearableCollections(
 386            int pageNumber, int pageSize,
 387            List<WearableItem> wearableBuffer,
 388            CancellationToken cancellationToken)
 389        {
 47390            IReadOnlyList<string> customCollections =
 391                await customNftCollectionService.GetConfiguredCustomNftCollectionAsync(cancellationToken);
 392
 47393            HashSet<string> collectionsToRequest = HashSetPool<string>.Get();
 394
 98395            foreach (string collectionId in customCollections)
 2396                if (!collectionId.StartsWith("urn", StringComparison.OrdinalIgnoreCase))
 1397                    collectionsToRequest.Add(collectionId);
 398
 47399            (IReadOnlyList<WearableItem> _, int totalAmount) = await wearablesCatalogService.RequestWearableCollectionIn
 400                collectionsToRequest, cancellationToken,
 401                collectionBuffer: wearableBuffer,
 402                nameFilter: nameFilter,
 403                pageNumber: pageNumber, pageSize: pageSize);
 404
 47405            HashSetPool<string>.Release(collectionsToRequest);
 406
 47407            return totalAmount;
 47408        }
 409
 410        private WearableGridItemModel ToWearableGridModel(WearableItem wearable)
 411        {
 412            NftRarity rarity;
 413
 21414            if (string.IsNullOrEmpty(wearable.rarity))
 0415                rarity = NftRarity.None;
 21416            else if (!Enum.TryParse(wearable.rarity, true, out NftRarity result))
 417            {
 0418                rarity = NftRarity.None;
 0419                Debug.LogWarning($"Could not parse the rarity \"{wearable.rarity}\" of the wearable '{wearable.id}'. Fal
 420            }
 421            else
 21422                rarity = result;
 423
 21424            string currentBodyShapeId = dataStoreBackpackV2.previewBodyShape.Get();
 425
 21426            return new WearableGridItemModel
 427            {
 428                WearableId = wearable.id,
 429                Rarity = rarity,
 430                Category = wearable.data.category,
 431                ImageUrl = wearable.ComposeThumbnailUrl(),
 432                IsEquipped = IsEquipped(ExtendedUrnParser.GetShortenedUrn(wearable.id)),
 433                IsNew = (DateTime.UtcNow - wearable.MostRecentTransferredDate).TotalHours < 24,
 434                IsSelected = false,
 435                UnEquipAllowed = wearable.CanBeUnEquipped(),
 436                IsCompatibleWithBodyShape = IsCompatibleWithBodyShape(currentBodyShapeId, wearable),
 437                IsSmartWearable = wearable.IsSmart(),
 438                Amount = wearable.amount > 1 ? $"x{wearable.amount.ToString()}" : "",
 439            };
 440        }
 441
 442        private bool IsEquipped(string wearableId) =>
 22443            dataStoreBackpackV2.previewEquippedWearables.Contains(wearableId)
 444            || wearableId == dataStoreBackpackV2.previewBodyShape.Get();
 445
 446        private void HandleWearableSelected(WearableGridItemModel wearableGridItem)
 447        {
 1448            string wearableId = wearableGridItem.WearableId;
 1449            string shortenedWearableId = ExtendedUrnParser.GetShortenedUrn(wearableId);
 450
 1451            view.ClearWearableSelection();
 1452            view.SelectWearable(shortenedWearableId);
 453
 1454            if (!wearablesCatalogService.WearablesCatalog.TryGetValue(wearableId, out WearableItem wearable))
 455            {
 0456                Debug.LogError($"Cannot fill the wearable info card, the wearable id does not exist {wearableId}");
 0457                return;
 458            }
 459
 1460            string[] hidesList = wearable.GetHidesList(userProfileBridge.GetOwn().avatar.bodyShape);
 461
 1462            view.FillInfoCard(new InfoCardComponentModel
 463            {
 464                rarity = wearable.rarity,
 465                category = wearable.data.category,
 466                description = string.IsNullOrEmpty(wearable.description) ? EMPTY_WEARABLE_DESCRIPTION : wearable.descrip
 467                imageUri = wearable.ComposeThumbnailUrl(),
 468
 469                // TODO: solve hidden by field
 470                hiddenBy = null,
 471                name = wearable.GetName(),
 472                hideList = hidesList != null ? hidesList.ToList() : new List<string>(),
 473                isEquipped = IsEquipped(shortenedWearableId),
 474                removeList = wearable.data.replaces != null ? wearable.data.replaces.ToList() : new List<string>(),
 475                wearableId = wearableId,
 476                unEquipAllowed = wearable.CanBeUnEquipped(),
 477                blockVrmExport = wearable.data.blockVrmExport,
 478            });
 479
 1480            OnWearableSelected?.Invoke(wearableId);
 1481        }
 482
 483        private void HandleWearableUnequipped(WearableGridItemModel wearableGridItem, UnequipWearableSource source) =>
 3484            OnWearableUnequipped?.Invoke(wearableGridItem.WearableId, source);
 485
 486        private void HandleWearableEquipped(WearableGridItemModel wearableGridItem, EquipWearableSource source) =>
 13487            OnWearableEquipped?.Invoke(wearableGridItem.WearableId, source);
 488
 489        private void FilterWearablesFromReferencePath(string referencePath)
 490        {
 4491            string[] filters = referencePath.Split('&', StringSplitOptions.RemoveEmptyEntries);
 492
 4493            nameFilter = null;
 4494            categoryFilter = null;
 495
 28496            foreach (string filter in filters)
 497            {
 10498                if (filter.StartsWith(NAME_FILTER_REF))
 3499                    nameFilter = filter[5..];
 7500                else if (filter.StartsWith(CATEGORY_FILTER_REF))
 3501                    categoryFilter = filter[9..];
 502            }
 503
 4504            requestWearablesCancellationToken = requestWearablesCancellationToken.SafeRestart();
 4505            ShowWearablesAndUpdateFilters(1, requestWearablesCancellationToken.Token).Forget();
 4506        }
 507
 508        private void RemoveFiltersFromReferencePath(string referencePath)
 509        {
 4510            string[] filters = referencePath.Split('&', StringSplitOptions.RemoveEmptyEntries);
 4511            string filter = filters[^1];
 512
 4513            if (filter.StartsWith(NAME_FILTER_REF))
 2514                nameFilter = null;
 2515            else if (filter.StartsWith(CATEGORY_FILTER_REF))
 2516                categoryFilter = null;
 517
 4518            requestWearablesCancellationToken = requestWearablesCancellationToken.SafeRestart();
 4519            ShowWearablesAndUpdateFilters(1, requestWearablesCancellationToken.Token).Forget();
 4520        }
 521
 522        private void GoToMarketplace()
 523        {
 2524            browserBridge.OpenUrl(userProfileBridge.GetOwn().hasConnectedWeb3
 525                ? URL_MARKET_PLACE
 526                : URL_GET_A_WALLET);
 2527        }
 528
 529        private void SetThirdPartCollectionIds(HashSet<string> selectedCollections)
 530        {
 0531            thirdPartyCollectionIdsFilter = selectedCollections;
 0532            filtersCancellationToken = filtersCancellationToken.SafeRestart();
 0533            ThrottleLoadWearablesWithCurrentFilters(filtersCancellationToken.Token).Forget();
 0534            view.SetInfoCardVisible(false);
 0535        }
 536
 537        private void SetSorting((NftOrderByOperation type, bool directionAscendent) newSorting)
 538        {
 1539            wearableSorting = newSorting;
 1540            filtersCancellationToken = filtersCancellationToken.SafeRestart();
 1541            ThrottleLoadWearablesWithCurrentFilters(filtersCancellationToken.Token).Forget();
 1542            view.SetInfoCardVisible(false);
 1543            backpackAnalyticsService.SendWearableSortedBy(newSorting.type, newSorting.directionAscendent);
 1544        }
 545
 546        private void SetNameFilterFromSearchText(string newText)
 547        {
 1548            categoryFilter = null;
 1549            collectionTypeMask = NftCollectionType.All;
 1550            thirdPartyCollectionIdsFilter?.Clear();
 1551            nameFilter = newText;
 1552            filtersCancellationToken = filtersCancellationToken.SafeRestart();
 1553            ThrottleLoadWearablesWithCurrentFilters(filtersCancellationToken.Token).Forget();
 1554            view.SetInfoCardVisible(false);
 1555            backpackAnalyticsService.SendWearableSearch(newText);
 1556        }
 557
 558        private void SetCollectionTypeFromFilterSelection(NftCollectionType collectionType)
 559        {
 0560            nameFilter = null;
 0561            collectionTypeMask = collectionType;
 0562            filtersCancellationToken = filtersCancellationToken.SafeRestart();
 0563            ThrottleLoadWearablesWithCurrentFilters(filtersCancellationToken.Token).Forget();
 0564            view.SetInfoCardVisible(false);
 0565            backpackAnalyticsService.SendWearableFilter(!collectionType.HasFlag(NftCollectionType.Base));
 0566        }
 567
 568        private void SetCategoryFromFilterSelection(string category, bool supportColor, PreviewCameraFocus previewCamera
 569        {
 5570            nameFilter = null;
 5571            SetCategory(category, isSelected);
 5572        }
 573
 574        private void SetCategory(string category, bool isSelected)
 575        {
 5576            categoryFilter = isSelected ? category : null;
 5577            filtersCancellationToken = filtersCancellationToken.SafeRestart();
 5578            ThrottleLoadWearablesWithCurrentFilters(filtersCancellationToken.Token).Forget();
 5579            view.SetInfoCardVisible(false);
 5580        }
 581
 582        private async UniTaskVoid ThrottleLoadWearablesWithCurrentFilters(CancellationToken cancellationToken)
 583        {
 21584            await UniTask.NextFrame(cancellationToken);
 3585            LoadWearables();
 3586        }
 587
 588        private bool IsCompatibleWithBodyShape(string bodyShapeId, WearableItem wearable)
 589        {
 23590            bool isCompatibleWithBodyShape = wearable.data.category
 591                                                 is WearableLiterals.Categories.BODY_SHAPE
 592                                                 or WearableLiterals.Categories.SKIN
 593                                             || wearable.SupportsBodyShape(bodyShapeId);
 594
 7595            return isCompatibleWithBodyShape;
 596        }
 597    }
 598}

Methods/Properties

WearableGridController(DCL.Backpack.IWearableGridView, IUserProfileBridge, DCLServices.WearablesCatalogService.IWearablesCatalogService, DCL.DataStore_BackpackV2, DCL.Browser.IBrowserBridge, DCL.Backpack.BackpackFiltersController, DCL.Backpack.AvatarSlotsHUDController, DCL.Backpack.IBackpackAnalyticsService, DCLServices.CustomNftCollection.ICustomNftCollectionService)
Dispose()
LoadWearables()
LoadWearablesWithFilters(System.String, DCLServices.WearablesCatalogService.NftCollectionType, System.Collections.Generic.ICollection[String], System.String, System.Nullable[ValueTuple`2])
CancelWearableLoading()
Equip(System.String)
UnEquip(System.String)
UpdateBodyShapeCompatibility(System.String)
LoadCollections()
ResetFilters()
ShowWearablesAndUpdateFilters()
HandleNewPageRequested(System.Int32)
RequestWearablesAndShowThem()
MergeCustomWearableItems()
MergePublishedWearableCollections()
MergeToWearableResults()
MergeBuilderWearableCollections()
FetchCustomWearableItems()
FetchPublishedWearableCollections()
FetchBuilderWearableCollections()
ToWearableGridModel(WearableItem)
IsEquipped(System.String)
HandleWearableSelected(DCL.Backpack.WearableGridItemModel)
HandleWearableUnequipped(DCL.Backpack.WearableGridItemModel, DCL.Backpack.UnequipWearableSource)
HandleWearableEquipped(DCL.Backpack.WearableGridItemModel, DCL.Backpack.EquipWearableSource)
FilterWearablesFromReferencePath(System.String)
RemoveFiltersFromReferencePath(System.String)
GoToMarketplace()
SetThirdPartCollectionIds(System.Collections.Generic.HashSet[String])
SetSorting(System.ValueTuple[NftOrderByOperation,Boolean])
SetNameFilterFromSearchText(System.String)
SetCollectionTypeFromFilterSelection(DCLServices.WearablesCatalogService.NftCollectionType)
SetCategoryFromFilterSelection(System.String, System.Boolean, MainScripts.DCL.Controllers.HUD.CharacterPreview.PreviewCameraFocus, System.Boolean)
SetCategory(System.String, System.Boolean)
ThrottleLoadWearablesWithCurrentFilters()
IsCompatibleWithBodyShape(System.String, WearableItem)