< Summary

Class:DCL.MyAccount.EmailNotificationsController
Assembly:MyAccountHUD
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/MyAccountHUD/EmailNotificationsController.cs
Covered lines:0
Uncovered lines:126
Coverable lines:126
Total lines:257
Line coverage:0% (0 of 126)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:12
Method coverage:0% (0 of 12)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
EmailNotificationsController(...)0%2100%
Dispose()0%2100%
OnMyAccountSectionOpen(...)0%12300%
OnMyAccountSectionTabChanged(...)0%6200%
RefreshForm()0%2100%
OnEmailEdited(...)0%12300%
OnEmailSubmitted(...)0%12300%
SetSavedEmail()0%2100%
OnReSendConfirmationEmailClicked()0%2100%
IsValidEmail(...)0%6200%
LoadEmailAsync()0%72800%
UpdateEmailAsync()0%3421800%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/MyAccountHUD/EmailNotificationsController.cs

#LineLine coverage
 1using Cysharp.Threading.Tasks;
 2using DCL.Helpers;
 3using DCL.Tasks;
 4using DCLServices.SubscriptionsAPIService;
 5using SocialFeaturesAnalytics;
 6using System;
 7using System.Net.Mail;
 8using System.Threading;
 9using UnityEngine;
 10
 11namespace DCL.MyAccount
 12{
 13    public class EmailNotificationsController
 14    {
 15        private enum ConfirmationModalStatus
 16        {
 17            None,
 18            Accepted,
 19            Rejected,
 20        }
 21
 22        private const string CURRENT_SUBSCRIPTION_ID_LOCAL_STORAGE_KEY = "currentSubscriptionId";
 23
 24        private readonly IEmailNotificationsComponentView view;
 25        private readonly IUpdateEmailConfirmationHUDComponentView updateEmailConfirmationHUDComponentView;
 26        private readonly MyAccountSectionHUDController myAccountSectionHUDController;
 27        private readonly DataStore dataStore;
 28        private readonly ISubscriptionsAPIService subscriptionsAPIService;
 29        private readonly ISocialAnalytics socialAnalytics;
 30
 31        private CancellationTokenSource loadEmailCancellationToken;
 32        private CancellationTokenSource updateEmailCancellationToken;
 33
 34        private string savedEmail;
 35        private bool savedIsPending;
 36        private ConfirmationModalStatus confirmationModalStatus = ConfirmationModalStatus.None;
 37
 038        public EmailNotificationsController(
 39            IEmailNotificationsComponentView view,
 40            IUpdateEmailConfirmationHUDComponentView updateEmailConfirmationHUDComponentView,
 41            MyAccountSectionHUDController myAccountSectionHUDController,
 42            DataStore dataStore,
 43            ISubscriptionsAPIService subscriptionsAPIService,
 44            ISocialAnalytics socialAnalytics)
 45        {
 046            this.view = view;
 047            this.updateEmailConfirmationHUDComponentView = updateEmailConfirmationHUDComponentView;
 048            this.myAccountSectionHUDController = myAccountSectionHUDController;
 049            this.dataStore = dataStore;
 050            this.subscriptionsAPIService = subscriptionsAPIService;
 051            this.socialAnalytics = socialAnalytics;
 52
 053            dataStore.myAccount.isMyAccountSectionVisible.OnChange += OnMyAccountSectionOpen;
 054            dataStore.myAccount.openSection.OnChange += OnMyAccountSectionTabChanged;
 055            view.OnEmailEdited += OnEmailEdited;
 056            view.OnEmailSubmitted += OnEmailSubmitted;
 057            view.OnReSendConfirmationEmailClicked += OnReSendConfirmationEmailClicked;
 058            updateEmailConfirmationHUDComponentView.OnConfirmationModalAccepted += isAccepted => confirmationModalStatus
 059        }
 60
 61        public void Dispose()
 62        {
 063            loadEmailCancellationToken.SafeCancelAndDispose();
 064            updateEmailCancellationToken.SafeCancelAndDispose();
 065            dataStore.myAccount.isMyAccountSectionVisible.OnChange -= OnMyAccountSectionOpen;
 066            dataStore.myAccount.openSection.OnChange -= OnMyAccountSectionTabChanged;
 067            view.OnEmailEdited -= OnEmailEdited;
 068            view.OnEmailSubmitted -= OnEmailSubmitted;
 069            view.OnReSendConfirmationEmailClicked -= OnReSendConfirmationEmailClicked;
 070        }
 71
 72        private void OnMyAccountSectionOpen(bool isVisible, bool _)
 73        {
 074            if (!isVisible || dataStore.myAccount.openSection.Get() != MyAccountSection.EmailNotifications.ToString())
 075                return;
 76
 077            RefreshForm();
 078        }
 79
 80        private void OnMyAccountSectionTabChanged(string currentOpenSection, string _)
 81        {
 082            if (currentOpenSection != MyAccountSection.EmailNotifications.ToString())
 083                return;
 84
 085            RefreshForm();
 086        }
 87
 88        private void RefreshForm()
 89        {
 090            view.ResetForm();
 091            loadEmailCancellationToken = loadEmailCancellationToken.SafeRestart();
 092            LoadEmailAsync(loadEmailCancellationToken.Token).Forget();
 093            updateEmailConfirmationHUDComponentView.HideConfirmationModal();
 094        }
 95
 96        private void OnEmailEdited(string newEmail)
 97        {
 098            view.SetEmailFormValid(IsValidEmail(newEmail));
 099            view.SetStatusAsPending(newEmail == savedEmail && savedIsPending);
 0100        }
 101
 102        private void OnEmailSubmitted(string newEmail)
 103        {
 0104            if (!IsValidEmail(newEmail))
 105            {
 0106                SetSavedEmail();
 0107                return;
 108            }
 109
 0110            if (newEmail == savedEmail)
 0111                return;
 112
 0113            updateEmailCancellationToken = updateEmailCancellationToken.SafeRestart();
 0114            UpdateEmailAsync(newEmail, true, updateEmailCancellationToken.Token).Forget();
 0115        }
 116
 117        private void SetSavedEmail()
 118        {
 0119            view.SetEmail(savedEmail);
 0120            view.SetStatusAsPending(savedIsPending);
 0121            view.SetEmailFormValid(true);
 0122            view.SetEmailInputInteractable(true);
 0123            view.SetEmailUpdateLoadingActive(false);
 0124        }
 125
 126        private void OnReSendConfirmationEmailClicked()
 127        {
 0128            updateEmailCancellationToken = updateEmailCancellationToken.SafeRestart();
 0129            UpdateEmailAsync(savedEmail, false, updateEmailCancellationToken.Token).Forget();
 0130        }
 131
 132        private static bool IsValidEmail(string email)
 133        {
 0134            if (email.Length == 0)
 0135                return true;
 136
 137            try
 138            {
 0139                MailAddress mailAddress = new MailAddress(email);
 0140                return mailAddress.Address == email;
 141            }
 0142            catch
 143            {
 0144                return false;
 145            }
 0146        }
 147
 148        private async UniTaskVoid LoadEmailAsync(CancellationToken cancellationToken)
 149        {
 0150            view.SetLoadingActive(true);
 0151            savedEmail = string.Empty;
 0152            savedIsPending = false;
 153
 0154            if (!string.IsNullOrEmpty(PlayerPrefsBridge.GetString(CURRENT_SUBSCRIPTION_ID_LOCAL_STORAGE_KEY)))
 155            {
 0156                string subscriptionToGet = PlayerPrefsBridge.GetString(CURRENT_SUBSCRIPTION_ID_LOCAL_STORAGE_KEY);
 157
 158                try
 159                {
 0160                    var existingSubscription = await subscriptionsAPIService.GetSubscription(subscriptionToGet, cancella
 161
 0162                    if (existingSubscription != null)
 163                    {
 0164                        if (existingSubscription.status == "inactive")
 0165                            PlayerPrefsBridge.SetString(CURRENT_SUBSCRIPTION_ID_LOCAL_STORAGE_KEY, string.Empty);
 166                        else
 167                        {
 0168                            savedEmail = existingSubscription.email;
 0169                            savedIsPending = existingSubscription.status is not "active";
 170                        }
 171                    }
 0172                }
 0173                catch (Exception ex)
 174                {
 0175                    if (ex.Message.Contains("404"))
 0176                        PlayerPrefsBridge.SetString(CURRENT_SUBSCRIPTION_ID_LOCAL_STORAGE_KEY, string.Empty);
 177                    else
 0178                        Debug.LogError($"An error occurred while getting the email subscription '{subscriptionToGet}': {
 0179                }
 0180            }
 181
 0182            SetSavedEmail();
 0183            view.SetLoadingActive(false);
 0184        }
 185
 186        private async UniTaskVoid UpdateEmailAsync(string newEmail, bool needConfirmation, CancellationToken cancellatio
 187        {
 0188            var wasSuccessfullyUpdated = false;
 0189            view.SetEmailInputInteractable(false);
 0190            view.SetEmailUpdateLoadingActive(true);
 191
 0192            if (needConfirmation && !string.IsNullOrEmpty(savedEmail))
 193            {
 0194                confirmationModalStatus = ConfirmationModalStatus.None;
 0195                updateEmailConfirmationHUDComponentView.ShowConfirmationModal(
 196                    string.IsNullOrEmpty(newEmail) ? view.deleteEmailLogo : view.updateEmailLogo,
 197                    string.IsNullOrEmpty(newEmail) ? "Are you sure you want to unsubscribe from Decentraland's newslette
 198
 0199                await UniTask.WaitUntil(() => confirmationModalStatus != ConfirmationModalStatus.None, cancellationToken
 200            }
 201
 0202            if (confirmationModalStatus == ConfirmationModalStatus.Rejected)
 203            {
 0204                SetSavedEmail();
 0205                return;
 206            }
 207
 0208            if (!string.IsNullOrEmpty(PlayerPrefsBridge.GetString(CURRENT_SUBSCRIPTION_ID_LOCAL_STORAGE_KEY)))
 209            {
 0210                string subscriptionToDelete = PlayerPrefsBridge.GetString(CURRENT_SUBSCRIPTION_ID_LOCAL_STORAGE_KEY);
 211
 212                try
 213                {
 0214                    await subscriptionsAPIService.DeleteSubscription(subscriptionToDelete, cancellationToken);
 0215                    PlayerPrefsBridge.SetString(CURRENT_SUBSCRIPTION_ID_LOCAL_STORAGE_KEY, string.Empty);
 0216                    PlayerPrefsBridge.Save();
 0217                    savedEmail = string.Empty;
 0218                    savedIsPending = false;
 0219                    wasSuccessfullyUpdated = true;
 0220                }
 0221                catch (Exception ex)
 222                {
 0223                    wasSuccessfullyUpdated = false;
 0224                    Debug.LogError($"An error occurred while deleting the email subscription '{subscriptionToDelete}': {
 0225                }
 0226            }
 227
 0228            if (!string.IsNullOrEmpty(newEmail))
 229            {
 230                try
 231                {
 0232                    var newSubscription = await subscriptionsAPIService.CreateSubscription(newEmail, cancellationToken);
 0233                    PlayerPrefsBridge.SetString(CURRENT_SUBSCRIPTION_ID_LOCAL_STORAGE_KEY, newSubscription.id);
 0234                    PlayerPrefsBridge.Save();
 0235                    savedEmail = newEmail;
 0236                    savedIsPending = newSubscription.status is not "active";
 0237                    wasSuccessfullyUpdated = true;
 0238                }
 0239                catch (Exception ex)
 240                {
 0241                    wasSuccessfullyUpdated = false;
 0242                    Debug.LogError($"An error occurred while creating the subscription for {newEmail}: {ex.Message}");
 0243                }
 244            }
 245
 0246            view.SetEmailInputInteractable(true);
 0247            view.SetStatusAsPending(savedIsPending);
 0248            view.SetEmailUpdateLoadingActive(false);
 249
 0250            if (wasSuccessfullyUpdated)
 251            {
 0252                myAccountSectionHUDController.ShowAccountSettingsUpdatedToast();
 0253                socialAnalytics.SendProfileEdit(0, false, PlayerActionSource.EmailNotifications, ProfileField.Email);
 254            }
 0255        }
 256    }
 257}