| | 1 | | using DG.Tweening; |
| | 2 | | using System; |
| | 3 | | using System.Net.Mail; |
| | 4 | | using System.Text.RegularExpressions; |
| | 5 | | using TMPro; |
| | 6 | | using UnityEngine; |
| | 7 | | using UnityEngine.EventSystems; |
| | 8 | | using UnityEngine.UI; |
| | 9 | |
|
| | 10 | | namespace SignupHUD |
| | 11 | | { |
| | 12 | | public class SignupHUDV2View : BaseComponentView, ISignupHUDView, IPointerClickHandler |
| | 13 | | { |
| | 14 | | private const int MIN_NAME_LENGTH = 1; |
| | 15 | | private const int MAX_NAME_LENGTH = 15; |
| | 16 | |
|
| | 17 | | public event ISignupHUDView.NameScreenDone OnNameScreenNext; |
| | 18 | | public event Action OnEditAvatar; |
| | 19 | | public event Action OnTermsOfServiceAgreed; |
| | 20 | | public event Action OnTermsOfServiceBack; |
| | 21 | | public event Action<string> OnLinkClicked; |
| | 22 | |
|
| | 23 | | [SerializeField] internal TMP_InputField nameInputField; |
| | 24 | | [SerializeField] internal GameObject nameInputFieldFullOrInvalid; |
| | 25 | | [SerializeField] internal GameObject nameInputInvalidLabel; |
| | 26 | | [SerializeField] internal TextMeshProUGUI nameCurrentCharacters; |
| | 27 | | [SerializeField] internal GameObject nameCurrentCharactersReachedLimit; |
| | 28 | | [SerializeField] internal GameObject emailInputFieldInvalid; |
| | 29 | | [SerializeField] internal TMP_InputField emailInputField; |
| | 30 | | [SerializeField] internal GameObject emailInputInvalidLabel; |
| | 31 | | [SerializeField] internal Color colorForCharLimit; |
| | 32 | | [SerializeField] internal ToggleComponentView agreeTosAndPrivacyPolicyToggle; |
| | 33 | | [SerializeField] internal TMP_Text tosAndPrivacyPolicyText; |
| | 34 | | [SerializeField] internal Button termsOfServiceAgreeButton; |
| | 35 | | [SerializeField] internal Image termsOfServiceAgreeButtonIcon; |
| | 36 | |
|
| | 37 | | [Header("SignUp Mode Transitions")] |
| | 38 | | [SerializeField] internal RectTransform signUpRectTransform; |
| | 39 | | [SerializeField] internal CanvasGroup signUpCanvasGroup; |
| 0 | 40 | | [SerializeField] internal Ease transitionEase = Ease.InOutExpo; |
| 0 | 41 | | [SerializeField] internal float transitionDuration = 0.5f; |
| 0 | 42 | | [SerializeField] internal float transitionDistance = 200f; |
| | 43 | |
|
| | 44 | | private Vector2 originalAnchorPositionOfSignUp; |
| | 45 | |
|
| | 46 | | public override void Awake() |
| | 47 | | { |
| 0 | 48 | | originalAnchorPositionOfSignUp = signUpRectTransform.anchoredPosition; |
| | 49 | |
|
| 0 | 50 | | InitNameAndEmailScreen(); |
| 0 | 51 | | InitTermsOfServicesScreen(); |
| 0 | 52 | | } |
| | 53 | |
|
| 0 | 54 | | public override void RefreshControl() { } |
| | 55 | |
|
| | 56 | | public void SetVisibility(bool visible) |
| | 57 | | { |
| 0 | 58 | | PlayTransitionAnimation(visible); |
| | 59 | |
|
| 0 | 60 | | if (!visible) |
| 0 | 61 | | return; |
| | 62 | |
|
| 0 | 63 | | nameInputField.Select(); |
| 0 | 64 | | } |
| | 65 | |
|
| 0 | 66 | | public void ShowNameScreen() { } |
| | 67 | |
|
| 0 | 68 | | public void ShowTermsOfServiceScreen() { } |
| | 69 | |
|
| | 70 | | private void InitNameAndEmailScreen() |
| | 71 | | { |
| 0 | 72 | | SetTermsOfServiceAgreeButtonInteractable(false); |
| 0 | 73 | | nameCurrentCharacters.text = $"{0}/{MAX_NAME_LENGTH}"; |
| 0 | 74 | | nameInputField.characterLimit = MAX_NAME_LENGTH; |
| 0 | 75 | | nameInputInvalidLabel.SetActive(false); |
| 0 | 76 | | nameInputFieldFullOrInvalid.SetActive(false); |
| 0 | 77 | | emailInputFieldInvalid.SetActive(false); |
| 0 | 78 | | emailInputInvalidLabel.SetActive(false); |
| 0 | 79 | | nameCurrentCharactersReachedLimit.SetActive(false); |
| | 80 | |
|
| 0 | 81 | | nameInputField.onValueChanged.AddListener((text) => |
| | 82 | | { |
| 0 | 83 | | UpdateNameAndEmailNextButton(); |
| 0 | 84 | | nameCurrentCharacters.text = $"{text.Length} / {MAX_NAME_LENGTH}"; |
| 0 | 85 | | nameCurrentCharacters.color = text.Length < MAX_NAME_LENGTH ? Color.black : colorForCharLimit; |
| 0 | 86 | | nameCurrentCharactersReachedLimit.SetActive(text.Length >= MAX_NAME_LENGTH); |
| 0 | 87 | | nameInputInvalidLabel.SetActive(!IsValidName(text)); |
| 0 | 88 | | nameInputFieldFullOrInvalid.SetActive(text.Length >= MAX_NAME_LENGTH || !IsValidName(text)); |
| 0 | 89 | | }); |
| | 90 | |
|
| 0 | 91 | | emailInputField.onValueChanged.AddListener((text) => |
| | 92 | | { |
| 0 | 93 | | emailInputFieldInvalid.SetActive(!IsValidEmail(text)); |
| 0 | 94 | | emailInputInvalidLabel.SetActive(!IsValidEmail(text)); |
| 0 | 95 | | UpdateNameAndEmailNextButton(); |
| 0 | 96 | | }); |
| | 97 | |
|
| 0 | 98 | | agreeTosAndPrivacyPolicyToggle.OnSelectedChanged += (_, _, _) => |
| 0 | 99 | | UpdateNameAndEmailNextButton(); |
| 0 | 100 | | } |
| | 101 | |
|
| | 102 | | private void InitTermsOfServicesScreen() |
| | 103 | | { |
| 0 | 104 | | SetTermsOfServiceAgreeButtonInteractable(false); |
| 0 | 105 | | termsOfServiceAgreeButton.onClick.AddListener(() => |
| | 106 | | { |
| 0 | 107 | | OnNameScreenNext?.Invoke(nameInputField.text, emailInputField.text); |
| 0 | 108 | | OnTermsOfServiceAgreed?.Invoke(); |
| 0 | 109 | | }); |
| 0 | 110 | | } |
| | 111 | |
|
| | 112 | | private void UpdateNameAndEmailNextButton() |
| | 113 | | { |
| 0 | 114 | | string nameText = nameInputField.text; |
| 0 | 115 | | string emailText = emailInputField.text; |
| | 116 | |
|
| 0 | 117 | | SetTermsOfServiceAgreeButtonInteractable( |
| | 118 | | nameText.Length >= MIN_NAME_LENGTH && |
| | 119 | | IsValidName(nameText) && IsValidEmail(emailText) && |
| | 120 | | agreeTosAndPrivacyPolicyToggle.isOn); |
| 0 | 121 | | } |
| | 122 | |
|
| | 123 | | private bool IsValidEmail(string email) |
| | 124 | | { |
| 0 | 125 | | if (email.Length == 0) |
| 0 | 126 | | return true; |
| | 127 | |
|
| | 128 | | try |
| | 129 | | { |
| 0 | 130 | | MailAddress mailAddress = new MailAddress(email); |
| 0 | 131 | | return mailAddress.Address == email; |
| | 132 | | } |
| 0 | 133 | | catch |
| | 134 | | { |
| 0 | 135 | | return false; |
| | 136 | | } |
| 0 | 137 | | } |
| | 138 | |
|
| | 139 | | private static bool IsValidName(string nameText) => |
| 0 | 140 | | Regex.IsMatch(nameText, "^[a-zA-Z0-9]*$"); |
| | 141 | |
|
| | 142 | | public void OnPointerClick(PointerEventData eventData) |
| | 143 | | { |
| 0 | 144 | | int linkIndex = TMP_TextUtilities.FindIntersectingLink(tosAndPrivacyPolicyText, Input.mousePosition, null); |
| 0 | 145 | | if (linkIndex == -1) |
| 0 | 146 | | return; |
| | 147 | |
|
| 0 | 148 | | TMP_LinkInfo linkInfo = tosAndPrivacyPolicyText.textInfo.linkInfo[linkIndex]; |
| 0 | 149 | | OnLinkClicked?.Invoke(linkInfo.GetLinkID()); |
| 0 | 150 | | } |
| | 151 | |
|
| | 152 | | private void SetTermsOfServiceAgreeButtonInteractable(bool isInteractable) |
| | 153 | | { |
| 0 | 154 | | termsOfServiceAgreeButton.interactable = isInteractable; |
| 0 | 155 | | termsOfServiceAgreeButtonIcon.color = new Color(termsOfServiceAgreeButtonIcon.color.r, termsOfServiceAgreeBu |
| 0 | 156 | | } |
| | 157 | |
|
| | 158 | | private void PlayTransitionAnimation(bool visible) |
| | 159 | | { |
| 0 | 160 | | Vector2 signUpEndPosition = originalAnchorPositionOfSignUp; |
| 0 | 161 | | if (!visible) |
| 0 | 162 | | signUpEndPosition.x -= transitionDistance; |
| 0 | 163 | | signUpRectTransform.DOAnchorPos(signUpEndPosition, transitionDuration).SetEase(transitionEase); |
| 0 | 164 | | signUpCanvasGroup.DOFade(visible ? 1f : 0f, transitionDuration).SetEase(transitionEase); |
| 0 | 165 | | signUpCanvasGroup.blocksRaycasts = visible; |
| 0 | 166 | | } |
| | 167 | | } |
| | 168 | | } |