< 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:97
Uncovered lines:24
Coverable lines:121
Total lines:259
Line coverage:80.1% (97 of 121)
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
 90029    internal Dictionary<string, ItemToggle> currentItemToggles = new Dictionary<string, ItemToggle>();
 90030    internal Dictionary<string, ItemToggle> newItemToggles = new Dictionary<string, ItemToggle>();
 90031    internal readonly Dictionary<string, WearableSettings> totalWearables = new Dictionary<string, WearableSettings>();
 90032    internal List<WearableSettings> availableWearables = new List<WearableSettings>();
 90033    internal readonly List<string> selectedItems = new List<string>();
 34
 35    private string currentBodyShape;
 90036    private int maxVisibleWearables = 9;
 37    private int lastPage;
 38
 90039    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    {
 6688100        if (!isActiveAndEnabled && !forceRebuild && !EnvironmentSettings.RUNNING_TESTS) return;
 6688101        itemToggleContainer.Setup(maxVisibleWearables);
 6688102        pageSelector.Setup(GetMaxPages(), forceRebuild);
 6688103        UpdateWearableList(lastPage);
 6688104    }
 105
 6688106    private int GetMaxPages() => Mathf.CeilToInt(availableWearables.Count / (float)maxVisibleWearables);
 107
 108    private void UpdateWearableList( int page )
 109    {
 6913110        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
 6913113        newItemToggles.Clear();
 114
 138260115        for (int itemToggleIndex = 0; itemToggleIndex < maxVisibleWearables; itemToggleIndex++)
 116        {
 62217117            var baseIndex = page * maxVisibleWearables;
 62217118            var wearableIndex = itemToggleIndex + baseIndex;
 119
 62217120            if (wearableIndex < availableWearables.Count)
 121            {
 6411122                WearableSettings wearableSettings = availableWearables[wearableIndex];
 6411123                var item = wearableSettings.Item;
 124
 6411125                if (!currentItemToggles.ContainsKey(item.id))
 126                {
 4242127                    var itemToggle = itemToggleContainer.LoadItem(itemToggleIndex, wearableSettings);
 4242128                    itemToggle.SetCallbacks(ToggleClicked, SellClicked);
 4242129                    itemToggle.SetLoadingSpinner(wearableSettings.isLoading);
 4242130                    newItemToggles[item.id] = itemToggle;
 4242131                }
 132                else
 133                {
 2169134                    newItemToggles[item.id] = currentItemToggles[item.id];
 135                }
 136
 6411137                if (selectedItems.Contains(item.id))
 431138                    newItemToggles[item.id].selected = true;
 431139            }
 140            else
 141            {
 55806142                itemToggleContainer.HideItem(itemToggleIndex);
 143            }
 144        }
 145
 6913146        currentItemToggles = new Dictionary<string, ItemToggle>(newItemToggles);
 6913147    }
 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    {
 4242157        if (item == null)
 0158            return;
 159
 4242160        if (totalWearables.ContainsKey(item.id))
 0161            return;
 162
 4242163        WearableSettings wearableSettings = new WearableSettings(item, collectionName, amount, hideOtherWearablesToastSt
 4242164        totalWearables.Add(item.id, wearableSettings);
 165
 4242166        availableWearables.Add(wearableSettings);
 4242167    }
 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    {
 2718182        totalWearables.Clear();
 2718183        availableWearables.Clear();
 2718184        currentItemToggles.Clear();
 185
 2718186        UpdateSelectorLayout();
 2718187    }
 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    {
 5634200        SetupWearablePagination();
 5634201    }
 202
 203    private void RefreshAvailableWearables()
 204    {
 1054205        availableWearables = totalWearables.Values.ToList();
 1054206        SetupWearablePagination();
 1054207    }
 208
 209    public void Select(string itemID)
 210    {
 2242211        selectedItems.Add(itemID);
 2242212        ItemToggle toggle = GetItemToggleByID(itemID);
 2242213        if (toggle != null)
 1152214            toggle.selected = true;
 2242215    }
 216
 217    public void SetWearableLoadingSpinner(string wearableID, bool isActive)
 218    {
 3108219        if (totalWearables.ContainsKey(wearableID))
 220        {
 1554221            totalWearables[wearableID].isLoading = isActive;
 222        }
 223
 3108224        ItemToggle toggle = GetItemToggleByID(wearableID);
 3108225        if (toggle != null)
 1554226            toggle.SetLoadingSpinner(isActive);
 3108227    }
 228
 229    public void Unselect(string itemID)
 230    {
 928231        selectedItems.Remove(itemID);
 928232        ItemToggle toggle = GetItemToggleByID(itemID);
 928233        if (toggle != null)
 464234            toggle.selected = false;
 928235    }
 236
 237    public void UnselectAll()
 238    {
 1813239        selectedItems.Clear();
 1813240        using (var iterator = currentItemToggles.GetEnumerator())
 241        {
 4635242            while (iterator.MoveNext())
 243            {
 2822244                iterator.Current.Value.selected = false;
 245            }
 1813246        }
 1813247    }
 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    {
 6278255        if (string.IsNullOrEmpty(itemID))
 0256            return null;
 6278257        return currentItemToggles.ContainsKey(itemID) ? currentItemToggles[itemID] : null;
 258    }
 259}