< Summary

Class:ItemSelector
Assembly:AvatarEditorHUD
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/ItemSelector.cs
Covered lines:0
Uncovered lines:119
Coverable lines:119
Total lines:259
Line coverage:0% (0 of 119)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:23
Method coverage:0% (0 of 23)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ItemSelector()0%2100%
Awake()0%2100%
OnEnable()0%2100%
OnDestroy()0%2100%
OnScreenSizeChanged(...)0%2100%
CheckScreenSize()0%2100%
CheckScreenSizeAsync()0%12300%
SetupWearablePagination(...)0%20400%
GetMaxPages()0%2100%
UpdateWearableList(...)0%30500%
AddWearable(...)0%12300%
RemoveWearable(...)0%6200%
RemoveAllWearables()0%2100%
SetBodyShape(...)0%6200%
UpdateSelectorLayout()0%2100%
RefreshAvailableWearables()0%2100%
Select(...)0%6200%
SetWearableLoadingSpinner(...)0%12300%
Unselect(...)0%6200%
UnselectAll()0%6200%
ToggleClicked(...)0%6200%
SellClicked(...)0%6200%
GetItemToggleByID(...)0%12300%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/ItemSelector.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Runtime.CompilerServices;
 5using System.Threading;
 6using Cysharp.Threading.Tasks;
 7using DCL;
 8using DCL.Configuration;
 9using UnityEngine;
 10using UnityEngine.UI;
 11#pragma warning disable CS4014
 12
 13[assembly: InternalsVisibleTo("AvatarEditorHUDTests")]
 14
 15public class ItemSelector : MonoBehaviour
 16{
 17    private const int MIN_SCREEN_SIZE = 200;
 18    private const int AVATAR_MARGIN = 450;
 19    private const float ASPECT_RATIO_PER_COLUMN = 0.15f;
 20    private const int TOTAL_ROWS_OF_ITEMS = 3;
 21    private const int MIN_AMOUNT_OF_COLUMNS = 3;
 22
 23    [SerializeField] internal UIPageSelector pageSelector;
 24    [SerializeField] internal ItemToggleContainer itemToggleContainer;
 25
 26    public event Action<string> OnItemClicked;
 27    public event Action<string> OnSellClicked;
 28
 029    internal Dictionary<string, ItemToggle> currentItemToggles = new Dictionary<string, ItemToggle>();
 030    internal Dictionary<string, ItemToggle> newItemToggles = new Dictionary<string, ItemToggle>();
 031    internal readonly Dictionary<string, WearableSettings> totalWearables = new Dictionary<string, WearableSettings>();
 032    internal List<WearableSettings> availableWearables = new List<WearableSettings>();
 033    internal readonly List<string> selectedItems = new List<string>();
 34
 35    private string currentBodyShape;
 036    private int maxVisibleWearables = 9;
 37    private int lastPage;
 38
 039    private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
 40
 41    private void Awake()
 42    {
 043        Application.quitting += () =>
 44        {
 045            OnItemClicked = null;
 046        };
 47
 048        pageSelector.OnValueChanged += UpdateWearableList;
 049        DataStore.i.screen.size.OnChange += OnScreenSizeChanged;
 050    }
 51
 52    private void OnEnable()
 53    {
 054        CheckScreenSize();
 055    }
 56
 57    private void OnDestroy()
 58    {
 059        cancellationTokenSource.Cancel();
 060        cancellationTokenSource.Dispose();
 061    }
 62
 63    private void OnScreenSizeChanged(Vector2Int current, Vector2Int previous)
 64    {
 065        CheckScreenSize();
 066    }
 67
 68    private void CheckScreenSize()
 69    {
 070        cancellationTokenSource.Cancel();
 071        cancellationTokenSource.Dispose();
 072        cancellationTokenSource = new CancellationTokenSource();
 073        CheckScreenSizeAsync(cancellationTokenSource.Token);
 074    }
 75
 76    private async UniTask CheckScreenSizeAsync(CancellationToken cancellationToken)
 77    {
 78        try {
 079            RectTransform rt = (RectTransform)transform;
 080            LayoutRebuilder.MarkLayoutForRebuild(rt);
 81
 082            await UniTask.NextFrame(PlayerLoopTiming.LastPostLateUpdate, cancellationToken);
 83
 084            cancellationToken.ThrowIfCancellationRequested();
 85
 086            var rect = rt.rect;
 087            var width = Mathf.Max(rect.width, MIN_SCREEN_SIZE);
 088            float itemAndSpaceSize = 130 + 32f;
 089            var columns =  Mathf.Max(Mathf.CeilToInt(width / itemAndSpaceSize), MIN_AMOUNT_OF_COLUMNS);
 90
 091            maxVisibleWearables = TOTAL_ROWS_OF_ITEMS * columns;
 92
 093            SetupWearablePagination(true);
 094        }
 095        catch (OperationCanceledException) { }
 096    }
 97
 98    private void SetupWearablePagination(bool forceRebuild = false)
 99    {
 0100        if (!isActiveAndEnabled && !forceRebuild && !EnvironmentSettings.RUNNING_TESTS) return;
 0101        itemToggleContainer.Setup(maxVisibleWearables);
 0102        pageSelector.Setup(GetMaxPages(), forceRebuild);
 0103        UpdateWearableList(lastPage);
 0104    }
 105
 0106    private int GetMaxPages() => Mathf.CeilToInt(availableWearables.Count / (float)maxVisibleWearables);
 107
 108    private void UpdateWearableList( int page )
 109    {
 0110        lastPage = page;
 111
 112        //we use this buffer to prevent items from being initialized with the same data twice after a screen resize or c
 0113        newItemToggles.Clear();
 114
 0115        for (int itemToggleIndex = 0; itemToggleIndex < maxVisibleWearables; itemToggleIndex++)
 116        {
 0117            var baseIndex = page * maxVisibleWearables;
 0118            var wearableIndex = itemToggleIndex + baseIndex;
 119
 0120            if (wearableIndex < availableWearables.Count)
 121            {
 0122                WearableSettings wearableSettings = availableWearables[wearableIndex];
 0123                var item = wearableSettings.Item;
 124
 0125                if (!currentItemToggles.ContainsKey(item.id))
 126                {
 0127                    var itemToggle = itemToggleContainer.LoadItem(itemToggleIndex, wearableSettings);
 0128                    itemToggle.SetCallbacks(ToggleClicked, SellClicked);
 0129                    itemToggle.SetLoadingSpinner(wearableSettings.isLoading);
 0130                    newItemToggles[item.id] = itemToggle;
 131                }
 132                else
 133                {
 0134                    newItemToggles[item.id] = currentItemToggles[item.id];
 135                }
 136
 0137                if (selectedItems.Contains(item.id))
 0138                    newItemToggles[item.id].selected = true;
 139            }
 140            else
 141            {
 0142                itemToggleContainer.HideItem(itemToggleIndex);
 143            }
 144        }
 145
 0146        currentItemToggles = new Dictionary<string, ItemToggle>(newItemToggles);
 0147    }
 148
 149    public void AddWearable(
 150        WearableItem item,
 151        string collectionName,
 152        int amount,
 153        Func<WearableItem, bool> hideOtherWearablesToastStrategy,
 154        Func<WearableItem, bool> replaceOtherWearablesToastStrategy,
 155        Func<WearableItem, bool> incompatibleWearableToastStrategy)
 156    {
 0157        if (item == null)
 0158            return;
 159
 0160        if (totalWearables.ContainsKey(item.id))
 0161            return;
 162
 0163        WearableSettings wearableSettings = new WearableSettings(item, collectionName, amount, hideOtherWearablesToastSt
 0164        totalWearables.Add(item.id, wearableSettings);
 165
 0166        availableWearables.Add(wearableSettings);
 0167    }
 168
 169    public void RemoveWearable(string itemID)
 170    {
 0171        if (string.IsNullOrEmpty(itemID))
 0172            return;
 173
 0174        totalWearables.Remove(itemID);
 0175        currentItemToggles.Remove(itemID);
 176
 0177        RefreshAvailableWearables();
 0178    }
 179
 180    public void RemoveAllWearables()
 181    {
 0182        totalWearables.Clear();
 0183        availableWearables.Clear();
 0184        currentItemToggles.Clear();
 185
 0186        UpdateSelectorLayout();
 0187    }
 188
 189    public void SetBodyShape(string bodyShape)
 190    {
 0191        if (currentBodyShape == bodyShape)
 0192            return;
 193
 0194        currentBodyShape = bodyShape;
 0195        RefreshAvailableWearables();
 0196    }
 197
 198    public void UpdateSelectorLayout()
 199    {
 0200        SetupWearablePagination();
 0201    }
 202
 203    private void RefreshAvailableWearables()
 204    {
 0205        availableWearables = totalWearables.Values.ToList();
 0206        SetupWearablePagination();
 0207    }
 208
 209    public void Select(string itemID)
 210    {
 0211        selectedItems.Add(itemID);
 0212        ItemToggle toggle = GetItemToggleByID(itemID);
 0213        if (toggle != null)
 0214            toggle.selected = true;
 0215    }
 216
 217    public void SetWearableLoadingSpinner(string wearableID, bool isActive)
 218    {
 0219        if (totalWearables.ContainsKey(wearableID))
 220        {
 0221            totalWearables[wearableID].isLoading = isActive;
 222        }
 223
 0224        ItemToggle toggle = GetItemToggleByID(wearableID);
 0225        if (toggle != null)
 0226            toggle.SetLoadingSpinner(isActive);
 0227    }
 228
 229    public void Unselect(string itemID)
 230    {
 0231        selectedItems.Remove(itemID);
 0232        ItemToggle toggle = GetItemToggleByID(itemID);
 0233        if (toggle != null)
 0234            toggle.selected = false;
 0235    }
 236
 237    public void UnselectAll()
 238    {
 0239        selectedItems.Clear();
 0240        using (var iterator = currentItemToggles.GetEnumerator())
 241        {
 0242            while (iterator.MoveNext())
 243            {
 0244                iterator.Current.Value.selected = false;
 245            }
 0246        }
 0247    }
 248
 0249    internal void ToggleClicked(ItemToggle toggle) { OnItemClicked?.Invoke(toggle.wearableItem.id); }
 250
 0251    private void SellClicked(ItemToggle toggle) { OnSellClicked?.Invoke(toggle.wearableItem.id); }
 252
 253    private ItemToggle GetItemToggleByID(string itemID)
 254    {
 0255        if (string.IsNullOrEmpty(itemID))
 0256            return null;
 0257        return currentItemToggles.ContainsKey(itemID) ? currentItemToggles[itemID] : null;
 258    }
 259}