< Summary

Class:WorldsSubSectionComponentController
Assembly:ExploreV2
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/ExploreV2/Scripts/Sections/PlacesAndEventsSection/SubSections/WorldsSubSection/WorldsSubSectionMenu/WorldsSubSectionComponentController.cs
Covered lines:71
Uncovered lines:48
Coverable lines:119
Total lines:256
Line coverage:59.6% (71 of 119)
Covered branches:0
Total branches:0
Covered methods:7
Total methods:18
Method coverage:38.8% (7 of 18)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
WorldsSubSectionComponentController(...)0%110100%
Dispose()0%440100%
View_OnVoteChanged(...)0%20400%
View_OnFavoritesClicked(...)0%12300%
FirstLoading()0%2100%
OpenTab()0%2100%
ApplySorting()0%12300%
RequestAllWorlds()0%220100%
RequestAllFromAPI()0%220100%
RequestAllFromAPIAsync()0%9.756052.94%
ShowMoreWorlds()0%220100%
ShowMoreWorldsAsync()0%3.213071.43%
ShowWorldDetailedInfo(...)0%2100%
JumpInToWorld(...)0%6200%
View_OnFriendHandlerAdded(...)0%2100%
OnChannelToJoinChanged(...)0%12300%
OpenWorldsDaoProposal()0%2100%
OpenWorldsInfo()0%2100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/ExploreV2/Scripts/Sections/PlacesAndEventsSection/SubSections/WorldsSubSection/WorldsSubSectionMenu/WorldsSubSectionComponentController.cs

#LineLine coverage
 1using Cysharp.Threading.Tasks;
 2using DCL;
 3using DCL.Browser;
 4using DCL.Interface;
 5using DCL.Social.Friends;
 6using DCL.Tasks;
 7using DCLServices.PlacesAPIService;
 8using DCLServices.WorldsAPIService;
 9using ExploreV2Analytics;
 10using System;
 11using System.Collections.Generic;
 12using System.Threading;
 13using Environment = DCL.Environment;
 14using static MainScripts.DCL.Controllers.HotScenes.IHotScenesController;
 15
 16public class WorldsSubSectionComponentController : IWorldsSubSectionComponentController, IPlacesAndEventsAPIRequester
 17{
 18    public event Action OnCloseExploreV2;
 19
 20    internal const int INITIAL_NUMBER_OF_ROWS = 4;
 21    private const int PAGE_SIZE = 12;
 22    private const string MOST_ACTIVE_FILTER_ID = "most_active";
 23    private const string DAO_PROPOSAL_LINK = "https://governance.decentraland.org/proposal/?id=c3216070-e822-11ed-b8f1-7
 24    private const string WORLDS_DOCS_LINK = "https://decentraland.org/blog/announcements/introducing-decentraland-worlds
 25
 26    internal readonly IWorldsSubSectionComponentView view;
 27    internal readonly IWorldsAPIService worldsAPIService;
 28    internal readonly IPlacesAPIService placesAPI;
 29    internal readonly FriendTrackerController friendsTrackerController;
 30    private readonly IExploreV2Analytics exploreV2Analytics;
 31    private readonly IPlacesAnalytics placesAnalytics;
 32    private readonly DataStore dataStore;
 33    private readonly IUserProfileBridge userProfileBridge;
 34    internal readonly IBrowserBridge browserBridge;
 35
 36    internal readonly PlaceAndEventsCardsReloader cardsReloader;
 37
 1538    internal readonly List<WorldsResponse.WorldInfo> worldsFromAPI = new ();
 39    internal int availableUISlots;
 1540    private CancellationTokenSource getWorldsCts = new ();
 1541    private CancellationTokenSource showMoreCts = new ();
 1542    private CancellationTokenSource disposeCts = new ();
 43
 1544    public WorldsSubSectionComponentController(
 45        IWorldsSubSectionComponentView view,
 46        IPlacesAPIService placesAPI,
 47        IWorldsAPIService worldsAPIService,
 48        IFriendsController friendsController,
 49        IExploreV2Analytics exploreV2Analytics,
 50        IPlacesAnalytics placesAnalytics,
 51        DataStore dataStore,
 52        IUserProfileBridge userProfileBridge,
 53        IBrowserBridge browserBridge)
 54    {
 1555        cardsReloader = new PlaceAndEventsCardsReloader(view, this, dataStore.exploreV2);
 56
 1557        this.view = view;
 1558        this.browserBridge = browserBridge;
 59
 1560        this.view.OnReady += FirstLoading;
 61
 1562        this.view.OnInfoClicked += ShowWorldDetailedInfo;
 1563        this.view.OnJumpInClicked += JumpInToWorld;
 1564        this.view.OnFavoriteClicked += View_OnFavoritesClicked;
 1565        this.view.OnVoteChanged += View_OnVoteChanged;
 1566        this.view.OnShowMoreWorldsClicked += ShowMoreWorlds;
 1567        this.view.OnOpenWorldsInfo += OpenWorldsInfo;
 1568        this.view.OnOpenWorldsDaoProposal += OpenWorldsDaoProposal;
 69
 1570        this.view.OnFriendHandlerAdded += View_OnFriendHandlerAdded;
 71
 1572        this.dataStore = dataStore;
 1573        this.dataStore.channels.currentJoinChannelModal.OnChange += OnChannelToJoinChanged;
 74
 1575        this.placesAPI = placesAPI;
 1576        this.worldsAPIService = worldsAPIService;
 77
 1578        friendsTrackerController = new FriendTrackerController(friendsController, view.currentFriendColors);
 79
 1580        this.exploreV2Analytics = exploreV2Analytics;
 1581        this.placesAnalytics = placesAnalytics;
 82
 1583        this.userProfileBridge = userProfileBridge;
 84
 1585        view.ConfigurePools();
 1586    }
 87
 88    public void Dispose()
 89    {
 1590        disposeCts?.SafeCancelAndDispose();
 1591        showMoreCts?.SafeCancelAndDispose();
 1592        getWorldsCts?.SafeCancelAndDispose();
 93
 1594        view.OnReady -= FirstLoading;
 1595        view.OnInfoClicked -= ShowWorldDetailedInfo;
 1596        view.OnJumpInClicked -= JumpInToWorld;
 1597        view.OnFavoriteClicked -= View_OnFavoritesClicked;
 1598        view.OnVoteChanged -= View_OnVoteChanged;
 1599        view.OnWorldsSubSectionEnable -= OpenTab;
 15100        view.OnSortingChanged -= ApplySorting;
 15101        view.OnFriendHandlerAdded -= View_OnFriendHandlerAdded;
 15102        view.OnShowMoreWorldsClicked -= ShowMoreWorlds;
 15103        this.view.OnOpenWorldsInfo -= OpenWorldsInfo;
 15104        this.view.OnOpenWorldsDaoProposal -= OpenWorldsDaoProposal;
 105
 15106        dataStore.channels.currentJoinChannelModal.OnChange -= OnChannelToJoinChanged;
 107
 15108        cardsReloader.Dispose();
 15109    }
 110
 111    private void View_OnVoteChanged(string worldId, bool? isUpvote)
 112    {
 0113        if (userProfileBridge.GetOwn().isGuest)
 0114            dataStore.HUDs.connectWalletModalVisible.Set(true);
 115        else
 116        {
 0117            if (isUpvote != null)
 118            {
 0119                if (isUpvote.Value)
 0120                    placesAnalytics.Like(worldId, IPlacesAnalytics.ActionSource.FromExplore, true);
 121                else
 0122                    placesAnalytics.Dislike(worldId, IPlacesAnalytics.ActionSource.FromExplore, true);
 123            }
 124            else
 0125                placesAnalytics.RemoveVote(worldId, IPlacesAnalytics.ActionSource.FromExplore, true);
 126
 0127            placesAPI.SetPlaceVote(isUpvote, worldId, disposeCts.Token);
 128        }
 0129    }
 130
 131    private void View_OnFavoritesClicked(string worldId, bool isFavorite)
 132    {
 0133        if (userProfileBridge.GetOwn().isGuest)
 0134            dataStore.HUDs.connectWalletModalVisible.Set(true);
 135        else
 136        {
 0137            if (isFavorite)
 0138                placesAnalytics.AddFavorite(worldId, IPlacesAnalytics.ActionSource.FromExplore, true);
 139            else
 0140                placesAnalytics.RemoveFavorite(worldId, IPlacesAnalytics.ActionSource.FromExplore, true);
 141
 0142            placesAPI.SetPlaceFavorite(worldId, isFavorite, disposeCts.Token);
 143        }
 0144    }
 145
 146    private void FirstLoading()
 147    {
 0148        view.OnWorldsSubSectionEnable += OpenTab;
 0149        view.OnSortingChanged += ApplySorting;
 0150        cardsReloader.Initialize();
 0151    }
 152
 153    private void OpenTab()
 154    {
 0155        exploreV2Analytics.SendWorldsTabOpen();
 0156        RequestAllWorlds();
 0157    }
 158
 159    private void ApplySorting()
 160    {
 0161        placesAnalytics.SortWorlds(view.sort == MOST_ACTIVE_FILTER_ID ? IPlacesAnalytics.SortingType.MostActive : IPlace
 0162        RequestAllWorlds();
 0163    }
 164
 165    internal void RequestAllWorlds()
 166    {
 2167        if (cardsReloader.CanReload())
 168        {
 2169            availableUISlots = view.CurrentTilesPerRow * INITIAL_NUMBER_OF_ROWS;
 2170            view.SetShowMoreButtonActive(false);
 171
 2172            cardsReloader.RequestAll();
 173        }
 2174    }
 175
 176    public void RequestAllFromAPI()
 177    {
 3178        getWorldsCts?.SafeCancelAndDispose();
 3179        getWorldsCts = CancellationTokenSource.CreateLinkedTokenSource(disposeCts.Token);
 180
 3181        RequestAllFromAPIAsync(getWorldsCts.Token).Forget();
 3182    }
 183
 184    private async UniTaskVoid RequestAllFromAPIAsync(CancellationToken ct)
 185    {
 186        try
 187        {
 3188            (IReadOnlyList<WorldsResponse.WorldInfo> worlds, int total) firstPage = await worldsAPIService.GetWorlds(0, 
 3189            friendsTrackerController.RemoveAllHandlers();
 3190            worldsFromAPI.Clear();
 3191            worldsFromAPI.AddRange(firstPage.worlds);
 3192            if (firstPage.total > PAGE_SIZE)
 193            {
 0194                (IReadOnlyList<WorldsResponse.WorldInfo> worlds, int total) secondPage = await worldsAPIService.GetWorld
 0195                worldsFromAPI.AddRange(secondPage.worlds);
 196            }
 197
 3198            view.SetWorlds(PlacesAndEventsCardsFactory.ConvertWorldsResponseToModel(worldsFromAPI, availableUISlots));
 3199            view.SetShowMoreWorldsButtonActive(worldsFromAPI.Count < firstPage.total);
 3200        }
 0201        catch (OperationCanceledException) { }
 3202    }
 203
 204    internal void ShowMoreWorlds()
 205    {
 2206        showMoreCts?.SafeCancelAndDispose();
 2207        showMoreCts = CancellationTokenSource.CreateLinkedTokenSource(disposeCts.Token);
 2208        ShowMoreWorldsAsync(showMoreCts.Token).Forget();
 2209    }
 210
 211    private async UniTask ShowMoreWorldsAsync(CancellationToken ct)
 212    {
 2213        (IReadOnlyList<WorldsResponse.WorldInfo> worlds, int total) = await worldsAPIService.GetWorlds((worldsFromAPI.Co
 214
 2215        worldsFromAPI.AddRange(worlds);
 2216        view.AddWorlds(PlacesAndEventsCardsFactory.ConvertWorldsResponseToModel(worlds));
 2217        view.SetShowMoreWorldsButtonActive(worldsFromAPI.Count < total);
 2218    }
 219
 220    internal void ShowWorldDetailedInfo(PlaceCardComponentModel worldModel)
 221    {
 0222        view.ShowWorldModal(worldModel);
 0223        exploreV2Analytics.SendClickOnWorldInfo(worldModel.placeInfo.id, worldModel.placeName);
 0224        dataStore.exploreV2.currentVisibleModal.Set(ExploreV2CurrentModal.Places);
 0225    }
 226
 227    internal void JumpInToWorld(PlaceInfo worldFromAPI)
 228    {
 0229        Environment.i.world.teleportController.JumpInWorld(worldFromAPI.world_name);
 0230        view.HideWorldModal();
 231
 0232        dataStore.exploreV2.currentVisibleModal.Set(ExploreV2CurrentModal.None);
 0233        OnCloseExploreV2?.Invoke();
 0234        exploreV2Analytics.SendWorldTeleport(worldFromAPI.id, worldFromAPI.title);
 0235    }
 236
 237    private void View_OnFriendHandlerAdded(IFriendTrackerHandler friendsHandler) =>
 0238        friendsTrackerController.AddHandler(friendsHandler);
 239
 240    private void OnChannelToJoinChanged(string currentChannelId, string previousChannelId)
 241    {
 0242        if (!string.IsNullOrEmpty(currentChannelId))
 0243            return;
 244
 0245        view.HideWorldModal();
 0246        dataStore.exploreV2.currentVisibleModal.Set(ExploreV2CurrentModal.None);
 0247        OnCloseExploreV2?.Invoke();
 0248    }
 249
 250    private void OpenWorldsDaoProposal() =>
 0251        browserBridge.OpenUrl(DAO_PROPOSAL_LINK);
 252
 253    private void OpenWorldsInfo() =>
 0254        browserBridge.OpenUrl(WORLDS_DOCS_LINK);
 255
 256}