< Summary

Class:DCL.Social.Chat.ChannelMembersHUDController
Assembly:WorldChatWindowHUD
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/WorldChatWindowHUD/ChannelMembersHUDController.cs
Covered lines:108
Uncovered lines:23
Coverable lines:131
Total lines:283
Line coverage:82.4% (108 of 131)
Covered branches:0
Total branches:0
Covered methods:20
Total methods:20
Method coverage:100% (20 of 20)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ChannelMembersHUDController(...)0%110100%
SetChannelId(...)0%3.793055.56%
SetMembersCount(...)0%110100%
Dispose()0%110100%
SetVisibility(...)0%220100%
LoadMembers()0%110100%
SearchMembers(...)0%220100%
<UpdateChannelMembers()0%26.5414060%
UpdateChannelMembers(...)0%110100%
IsUserBlocked(...)0%3.333066.67%
LoadMoreMembers()0%5.055087.5%
SetLoadingMoreVisible(...)0%3.043083.33%
SetAutomaticReloadingActive(...)0%220100%
ReloadMembersPeriodically()0%7.914037.5%
IsLoading()0%110100%
ClearListeners()0%110100%
WaitTimeoutThenHideLoading()0%6.984042.86%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/WorldChatWindowHUD/ChannelMembersHUDController.cs

#LineLine coverage
 1using System;
 2using System.Threading;
 3using Cysharp.Threading.Tasks;
 4using DCL.Chat.Channels;
 5using DCL.Tasks;
 6using System.Collections.Generic;
 7
 8namespace DCL.Social.Chat
 9{
 10    public class ChannelMembersHUDController : IDisposable
 11    {
 12        private const int LOAD_TIMEOUT = 2;
 13        private const int LOAD_PAGE_SIZE = 30;
 14        private const int MINUTES_FOR_AUTOMATIC_RELOADING = 1;
 15
 16        private readonly IChatController chatController;
 17        private readonly IUserProfileBridge userProfileBridge;
 18        private readonly DataStore_Channels dataStoreChannels;
 19        private readonly IChannelMembersComponentView view;
 2320        private readonly CancellationTokenSource showMembersCancellationToken = new ();
 21        private readonly UserProfile ownUserProfile;
 22
 2323        internal DateTime loadStartedTimestamp = DateTime.MinValue;
 24
 2325        private CancellationTokenSource loadingCancellationToken = new ();
 2326        private CancellationTokenSource reloadingCancellationToken = new ();
 27        private string currentChannelId;
 28        private int lastLimitRequested;
 29        private bool isSearching;
 30        private bool isVisible;
 31        private int currentMembersCount;
 32
 133        public IChannelMembersComponentView View => view;
 134        public string CurrentChannelId => currentChannelId;
 535        public bool IsVisible => isVisible;
 36
 2337        public ChannelMembersHUDController(IChannelMembersComponentView view, IChatController chatController,
 38            IUserProfileBridge userProfileBridge,
 39            DataStore_Channels dataStoreChannels)
 40        {
 2341            this.view = view;
 2342            this.chatController = chatController;
 2343            this.userProfileBridge = userProfileBridge;
 2344            this.dataStoreChannels = dataStoreChannels;
 45
 2346            ownUserProfile = userProfileBridge.GetOwn();
 2347        }
 48
 49        public void SetChannelId(string channelId)
 50        {
 1851            if (string.IsNullOrEmpty(channelId))
 052                return;
 53
 1854            currentChannelId = channelId;
 1855            lastLimitRequested = LOAD_PAGE_SIZE;
 56
 1857            if (isVisible)
 58            {
 059                LoadMembers();
 060                SetAutomaticReloadingActive(true);
 061                view.ClearSearchInput();
 62            }
 1863        }
 64
 65        public void SetMembersCount(int membersCount) =>
 966            currentMembersCount = membersCount;
 67
 68        public void Dispose()
 69        {
 2370            ClearListeners();
 2371            view.Dispose();
 2372            loadingCancellationToken.SafeCancelAndDispose();
 2373            reloadingCancellationToken.SafeCancelAndDispose();
 2374            showMembersCancellationToken.SafeCancelAndDispose();
 2375        }
 76
 77        public void SetVisibility(bool visible)
 78        {
 879            isVisible = visible;
 80
 881            if (visible)
 82            {
 783                LoadMembers();
 784                SetAutomaticReloadingActive(true);
 785                view.ClearSearchInput(notify: false);
 86            }
 87            else
 88            {
 189                SetAutomaticReloadingActive(false);
 190                ClearListeners();
 191                view.Hide();
 92            }
 193        }
 94
 95        private void LoadMembers()
 96        {
 797            ClearListeners();
 798            isSearching = false;
 99
 7100            view.OnSearchUpdated += SearchMembers;
 7101            view.OnRequestMoreMembers += LoadMoreMembers;
 7102            chatController.OnUpdateChannelMembers += UpdateChannelMembers;
 103
 7104            view.Show();
 7105            view.ClearAllEntries();
 7106            SetLoadingMoreVisible(false);
 7107            view.ShowLoading();
 108
 7109            loadStartedTimestamp = DateTime.Now;
 7110            string[] channelsToGetInfo = { currentChannelId };
 7111            chatController.GetChannelInfo(channelsToGetInfo);
 7112            chatController.GetChannelMembers(currentChannelId, lastLimitRequested, 0);
 113
 7114            loadingCancellationToken.Cancel();
 7115            loadingCancellationToken = new CancellationTokenSource();
 7116            WaitTimeoutThenHideLoading(loadingCancellationToken.Token).Forget();
 7117        }
 118
 119        private void SearchMembers(string searchText)
 120        {
 2121            loadStartedTimestamp = DateTime.Now;
 2122            view.ClearAllEntries();
 2123            SetLoadingMoreVisible(false);
 2124            view.ShowLoading();
 125
 2126            isSearching = !string.IsNullOrEmpty(searchText);
 127
 2128            if (!isSearching)
 129            {
 1130                chatController.GetChannelMembers(currentChannelId, lastLimitRequested, 0);
 1131                SetAutomaticReloadingActive(true);
 1132                view.HideResultsHeader();
 133            }
 134            else
 135            {
 1136                chatController.GetChannelMembers(currentChannelId, LOAD_PAGE_SIZE, 0, searchText);
 1137                SetAutomaticReloadingActive(false);
 1138                view.ShowResultsHeader();
 139            }
 140
 2141            loadingCancellationToken.Cancel();
 2142            loadingCancellationToken = new CancellationTokenSource();
 2143            WaitTimeoutThenHideLoading(loadingCancellationToken.Token).Forget();
 2144        }
 145
 146        private void UpdateChannelMembers(string channelId, ChannelMember[] channelMembers)
 147        {
 148            async UniTaskVoid UpdateChannelMembersAsync(IEnumerable<ChannelMember> channelMembers,
 149                CancellationToken cancellationToken)
 150            {
 1151                SetLoadingMoreVisible(true);
 1152                view.HideLoading();
 153
 6154                foreach (ChannelMember member in channelMembers)
 155                {
 2156                    UserProfile memberProfile = userProfileBridge.Get(member.userId);
 157
 4158                    try { memberProfile ??= await userProfileBridge.RequestFullUserProfileAsync(member.userId, cancellat
 0159                    catch (Exception e) when (e is not OperationCanceledException)
 160                    {
 0161                        var fallbackMemberEntry = new ChannelMemberEntryModel
 162                        {
 163                            isOnline = member.isOnline,
 164                            thumnailUrl = "",
 165                            userId = member.userId,
 166                            userName = member.userId,
 167                            isOptionsButtonHidden = member.userId == userProfileBridge.GetOwn().userId,
 168                            blocked = false
 169                        };
 170
 0171                        view.Set(fallbackMemberEntry);
 0172                    }
 173                    finally
 174                    {
 2175                        dataStoreChannels.SetAvailableMemberInChannel(member.userId, currentChannelId);
 176                    }
 177
 2178                    ChannelMemberEntryModel userToAdd = new ChannelMemberEntryModel
 179                    {
 180                        isOnline = member.isOnline,
 181                        thumnailUrl = memberProfile.face256SnapshotURL,
 182                        userId = memberProfile.userId,
 183                        userName = memberProfile.userName,
 184                        isOptionsButtonHidden = memberProfile.userId == userProfileBridge.GetOwn().userId,
 185                        blocked = IsUserBlocked(memberProfile.userId)
 186                    };
 187
 2188                    view.Set(userToAdd);
 2189                }
 190
 1191                if (isSearching)
 192                {
 0193                    SetLoadingMoreVisible(false);
 194
 0195                    if (view.EntryCount > 0)
 0196                        view.ShowResultsHeader();
 197                    else
 0198                        view.HideResultsHeader();
 199                }
 200                else
 1201                    SetLoadingMoreVisible(true);
 1202            }
 203
 1204            UpdateChannelMembersAsync(channelMembers, showMembersCancellationToken.Token).Forget();
 1205        }
 206
 207        private bool IsUserBlocked(string userId)
 208        {
 2209            if (ownUserProfile != null && ownUserProfile.blocked != null)
 0210                return ownUserProfile.blocked.Contains(userId);
 211
 2212            return false;
 213        }
 214
 215        private void LoadMoreMembers()
 216        {
 1217            if (IsLoading() ||
 218                isSearching ||
 0219                lastLimitRequested >= currentMembersCount) return;
 220
 1221            loadStartedTimestamp = DateTime.Now;
 1222            SetLoadingMoreVisible(false);
 1223            chatController.GetChannelMembers(currentChannelId, LOAD_PAGE_SIZE, view.EntryCount);
 224
 1225            if (!isSearching)
 1226                lastLimitRequested = LOAD_PAGE_SIZE + view.EntryCount;
 1227        }
 228
 229        private void SetLoadingMoreVisible(bool isVisible)
 230        {
 12231            if (isVisible)
 232            {
 2233                if (lastLimitRequested >= currentMembersCount)
 0234                    view.HideLoadingMore();
 235                else
 2236                    view.ShowLoadingMore();
 237            }
 238            else
 10239                view.HideLoadingMore();
 10240        }
 241
 242        public void SetAutomaticReloadingActive(bool isActive)
 243        {
 29244            reloadingCancellationToken.Cancel();
 245
 29246            if (isActive)
 247            {
 9248                reloadingCancellationToken = new CancellationTokenSource();
 9249                ReloadMembersPeriodically(reloadingCancellationToken.Token).Forget();
 250            }
 29251        }
 252
 253        private async UniTask ReloadMembersPeriodically(CancellationToken cancellationToken)
 254        {
 0255            while (true)
 256            {
 27257                await UniTask.Delay(MINUTES_FOR_AUTOMATIC_RELOADING * 60 * 1000, cancellationToken: cancellationToken);
 258
 0259                if (cancellationToken.IsCancellationRequested)
 0260                    return;
 261
 0262                LoadMembers();
 263            }
 0264        }
 265
 266        private bool IsLoading() =>
 1267            (DateTime.Now - loadStartedTimestamp).TotalSeconds < LOAD_TIMEOUT;
 268
 269        private void ClearListeners()
 270        {
 31271            view.OnSearchUpdated -= SearchMembers;
 31272            view.OnRequestMoreMembers -= LoadMoreMembers;
 31273            chatController.OnUpdateChannelMembers -= UpdateChannelMembers;
 31274        }
 275
 276        private async UniTask WaitTimeoutThenHideLoading(CancellationToken cancellationToken)
 277        {
 27278            await UniTask.Delay(LOAD_TIMEOUT * 1000, cancellationToken: cancellationToken);
 0279            if (cancellationToken.IsCancellationRequested) return;
 0280            view.HideLoading();
 0281        }
 282    }
 283}