< 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:95
Uncovered lines:24
Coverable lines:119
Total lines:259
Line coverage:79.8% (95 of 119)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ItemSelector()0%110100%
Awake()0%110100%
OnEnable()0%110100%
OnDestroy()0%110100%
OnScreenSizeChanged(...)0%2100%
CheckScreenSize()0%110100%
CheckScreenSizeAsync()0%4.123050%
SetupWearablePagination(...)0%4.074083.33%
GetMaxPages()0%110100%
UpdateWearableList(...)0%550100%
AddWearable(...)0%3.143075%
RemoveWearable(...)0%6200%
RemoveAllWearables()0%110100%
SetBodyShape(...)0%2.032080%
UpdateSelectorLayout()0%110100%
RefreshAvailableWearables()0%110100%
Select(...)0%220100%
SetWearableLoadingSpinner(...)0%330100%
Unselect(...)0%220100%
UnselectAll()0%220100%
ToggleClicked(...)0%6200%
SellClicked(...)0%6200%
GetItemToggleByID(...)0%3.333066.67%

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
 90129    internal Dictionary<string, ItemToggle> currentItemToggles = new Dictionary<string, ItemToggle>();
 90130    internal Dictionary<string, ItemToggle> newItemToggles = new Dictionary<string, ItemToggle>();
 90131    internal readonly Dictionary<string, WearableSettings> totalWearables = new Dictionary<string, WearableSettings>();
 90132    internal List<WearableSettings> availableWearables = new List<WearableSettings>();
 90133    internal readonly List<string> selectedItems = new List<string>();
 34
 35    private string currentBodyShape;
 90136    private int maxVisibleWearables = 9;
 37    private int lastPage;
 38
 90139    private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
 40
 41    private void Awake()
 42    {
 9443        Application.quitting += () =>
 44        {
 045            OnItemClicked = null;
 046        };
 47
 9448        pageSelector.OnValueChanged += UpdateWearableList;
 9449        DataStore.i.screen.size.OnChange += OnScreenSizeChanged;
 9450    }
 51
 52    private void OnEnable()
 53    {
 9454        CheckScreenSize();
 9455    }
 56
 57    private void OnDestroy()
 58    {
 9459        cancellationTokenSource.Cancel();
 9460        cancellationTokenSource.Dispose();
 9461    }
 62
 63    private void OnScreenSizeChanged(Vector2Int current, Vector2Int previous)
 64    {
 065        CheckScreenSize();
 066    }
 67
 68    private void CheckScreenSize()
 69    {
 9470        cancellationTokenSource.Cancel();
 9471        cancellationTokenSource.Dispose();
 9472        cancellationTokenSource = new CancellationTokenSource();
 9473        CheckScreenSizeAsync(cancellationTokenSource.Token);
 9474    }
 75
 76    private async UniTask CheckScreenSizeAsync(CancellationToken cancellationToken)
 77    {
 78        try {
 9479            RectTransform rt = (RectTransform)transform;
 9480            LayoutRebuilder.MarkLayoutForRebuild(rt);
 81
 28282            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        }
 18895        catch (OperationCanceledException) { }
 9496    }
 97
 98    private void SetupWearablePagination(bool forceRebuild = false)
 99    {
 5932100        if (!isActiveAndEnabled && !forceRebuild && !EnvironmentSettings.RUNNING_TESTS) return;
 5932101        itemToggleContainer.Setup(maxVisibleWearables);
 5932102        pageSelector.Setup(GetMaxPages(), forceRebuild);
 5932103        UpdateWearableList(lastPage);
 5932104    }
 105
 5932106    private int GetMaxPages() => Mathf.CeilToInt(availableWearables.Count / (float)maxVisibleWearables);
 107
 108    private void UpdateWearableList( int page )
 109    {
 6115110        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
 6115113        newItemToggles.Clear();
 114
 122300115        for (int itemToggleIndex = 0; itemToggleIndex < maxVisibleWearables; itemToggleIndex++)
 116        {
 55035117            var baseIndex = page * maxVisibleWearables;
 55035118            var wearableIndex = itemToggleIndex + baseIndex;
 119
 55035120            if (wearableIndex < availableWearables.Count)
 121            {
 5781122                WearableSettings wearableSettings = availableWearables[wearableIndex];
 5781123                var item = wearableSettings.Item;
 124
 5781125                if (!currentItemToggles.ContainsKey(item.id))
 126                {
 3654127                    var itemToggle = itemToggleContainer.LoadItem(itemToggleIndex, wearableSettings);
 3654128                    itemToggle.SetCallbacks(ToggleClicked, SellClicked);
 3654129                    itemToggle.SetLoadingSpinner(wearableSettings.isLoading);
 3654130                    newItemToggles[item.id] = itemToggle;
 131                }
 132                else
 133                {
 2127134                    newItemToggles[item.id] = currentItemToggles[item.id];
 135                }
 136
 5781137                if (selectedItems.Contains(item.id))
 275138                    newItemToggles[item.id].selected = true;
 139            }
 140            else
 141            {
 49254142                itemToggleContainer.HideItem(itemToggleIndex);
 143            }
 144        }
 145
 6115146        currentItemToggles = new Dictionary<string, ItemToggle>(newItemToggles);
 6115147    }
 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    {
 3654157        if (item == null)
 0158            return;
 159
 3654160        if (totalWearables.ContainsKey(item.id))
 0161            return;
 162
 3654163        WearableSettings wearableSettings = new WearableSettings(item, collectionName, amount, hideOtherWearablesToastSt
 3654164        totalWearables.Add(item.id, wearableSettings);
 165
 3654166        availableWearables.Add(wearableSettings);
 3654167    }
 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    {
 2340182        totalWearables.Clear();
 2340183        availableWearables.Clear();
 2340184        currentItemToggles.Clear();
 185
 2340186        UpdateSelectorLayout();
 2340187    }
 188
 189    public void SetBodyShape(string bodyShape)
 190    {
 1054191        if (currentBodyShape == bodyShape)
 0192            return;
 193
 1054194        currentBodyShape = bodyShape;
 1054195        RefreshAvailableWearables();
 1054196    }
 197
 198    public void UpdateSelectorLayout()
 199    {
 4878200        SetupWearablePagination();
 4878201    }
 202
 203    private void RefreshAvailableWearables()
 204    {
 1054205        availableWearables = totalWearables.Values.ToList();
 1054206        SetupWearablePagination();
 1054207    }
 208
 209    public void Select(string itemID)
 210    {
 1990211        selectedItems.Add(itemID);
 1990212        ItemToggle toggle = GetItemToggleByID(itemID);
 1990213        if (toggle != null)
 1026214            toggle.selected = true;
 1990215    }
 216
 217    public void SetWearableLoadingSpinner(string wearableID, bool isActive)
 218    {
 2736219        if (totalWearables.ContainsKey(wearableID))
 220        {
 1368221            totalWearables[wearableID].isLoading = isActive;
 222        }
 223
 2736224        ItemToggle toggle = GetItemToggleByID(wearableID);
 2736225        if (toggle != null)
 1368226            toggle.SetLoadingSpinner(isActive);
 2736227    }
 228
 229    public void Unselect(string itemID)
 230    {
 808231        selectedItems.Remove(itemID);
 808232        ItemToggle toggle = GetItemToggleByID(itemID);
 808233        if (toggle != null)
 404234            toggle.selected = false;
 808235    }
 236
 237    public void UnselectAll()
 238    {
 1456239        selectedItems.Clear();
 1456240        using (var iterator = currentItemToggles.GetEnumerator())
 241        {
 3732242            while (iterator.MoveNext())
 243            {
 2276244                iterator.Current.Value.selected = false;
 245            }
 1456246        }
 1456247    }
 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    {
 5534255        if (string.IsNullOrEmpty(itemID))
 0256            return null;
 5534257        return currentItemToggles.ContainsKey(itemID) ? currentItemToggles[itemID] : null;
 258    }
 259}