VanguardReMaster/client/Assets/Vanguard/Runtime/UI/LoginView.cs

205 lines
7.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using Vanguard.Api;
using Vanguard.App;
using Vanguard.Auth;
namespace Vanguard.UI
{
/// <summary>Экран входа/регистрации и выбора адреса сервера.</summary>
public sealed class LoginView
{
private readonly AppConfig _config;
private readonly AuthService _auth;
private readonly Action _onAuthenticated;
private readonly RectTransform _root;
private readonly InputField _serverUrl;
private readonly InputField _userName;
private readonly InputField _password;
private readonly Button _loginButton;
private readonly Button _registerButton;
private readonly Text _status;
private bool _busy;
public LoginView(
Transform parent,
AppConfig config,
AuthService auth,
Action onAuthenticated)
{
_config = config;
_auth = auth;
_onAuthenticated = onAuthenticated;
_root = UiKit.CreatePanel(parent, "LoginScreen", new Color(0.035f, 0.045f, 0.065f, 1f));
var card = UiKit.CreateCenteredCard(
_root,
"LoginCard",
new Vector2(640f, 790f),
new Color(0.07f, 0.085f, 0.115f, 1f));
UiKit.AddVerticalLayout(card, 36, 10);
var title = UiKit.CreateText(
card, "Title", "VANGUARD", 54, new Color(0.86f, 0.90f, 1f));
title.fontStyle = FontStyle.Bold;
UiKit.SetPreferredHeight(title, 64f);
var subtitle = UiKit.CreateText(
card, "Subtitle", "ReMaster · сетевой клиент", 20,
new Color(0.62f, 0.68f, 0.82f));
UiKit.SetPreferredHeight(subtitle, 34f);
AddCaption(card, "Сервер");
_serverUrl = UiKit.CreateInput(card, "ServerUrl", "http://192.168.31.158:18080");
_serverUrl.text = _config.ServerBaseUrl;
UiKit.SetPreferredHeight(_serverUrl, 54f);
AddCaption(card, "Имя игрока");
_userName = UiKit.CreateInput(card, "UserName", "3–32 символа");
UiKit.SetPreferredHeight(_userName, 54f);
AddCaption(card, "Пароль");
_password = UiKit.CreateInput(card, "Password", "8–128 символов", password: true);
UiKit.SetPreferredHeight(_password, 54f);
_loginButton = UiKit.CreateButton(card, "LoginButton", "Войти", OnLoginClicked);
UiKit.SetPreferredHeight(_loginButton, 56f);
_registerButton = UiKit.CreateButton(card, "RegisterButton", "Создать аккаунт", OnRegisterClicked, 21);
UiKit.SetPreferredHeight(_registerButton, 50f);
_status = UiKit.CreateText(
card, "Status", string.Empty, 18,
new Color(0.70f, 0.75f, 0.86f),
TextAnchor.UpperCenter);
_status.horizontalOverflow = HorizontalWrapMode.Wrap;
UiKit.SetPreferredHeight(_status, 72f);
var footer = UiKit.CreateText(
card,
"Footer",
"Стенд: 192.168.31.158:18080 · локально: localhost:5080",
15,
new Color(0.45f, 0.50f, 0.62f));
UiKit.SetPreferredHeight(footer, 26f);
}
public void Show(string status = null)
{
UiKit.SetActive(_root, true);
if (!string.IsNullOrEmpty(status))
SetStatus(status, new Color(0.70f, 0.75f, 0.86f));
}
public void Hide() => UiKit.SetActive(_root, false);
private static void AddCaption(Transform parent, string text)
{
var caption = UiKit.CreateText(
parent,
"Caption_" + text,
text,
17,
new Color(0.62f, 0.68f, 0.82f),
TextAnchor.MiddleLeft);
UiKit.SetPreferredHeight(caption, 24f);
}
private async void OnLoginClicked()
{
await SubmitAsync(register: false);
}
private async void OnRegisterClicked()
{
await SubmitAsync(register: true);
}
private async Task SubmitAsync(bool register)
{
if (_busy)
return;
var userName = (_userName.text ?? string.Empty).Trim();
var password = _password.text ?? string.Empty;
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
{
SetStatus("Введите имя игрока и пароль.", new Color(1f, 0.70f, 0.35f));
return;
}
_config.SetServerBaseUrl(_serverUrl.text);
_serverUrl.text = _config.ServerBaseUrl;
SetBusy(true, register ? "Создаём аккаунт…" : "Подключаемся…");
try
{
if (register)
await _auth.RegisterAsync(userName, password);
else
await _auth.LoginAsync(userName, password);
_password.text = string.Empty;
SetStatus("Готово.", new Color(0.45f, 0.85f, 0.55f));
_onAuthenticated();
}
catch (ApiException exception)
{
SetStatus(FormatError(exception), new Color(1f, 0.55f, 0.45f));
}
catch (Exception exception)
{
Debug.LogException(exception);
SetStatus("Не удалось связаться с сервером. Проверьте адрес.", new Color(1f, 0.55f, 0.45f));
}
finally
{
SetBusy(false, null);
}
}
private static string FormatError(ApiException exception)
{
if (exception.StatusCode == 0)
return "Нет связи с сервером. Проверьте адрес и запущен ли сервер.";
if (exception.Violations.Count > 0)
{
var details = string.Join("\n", exception.Violations.Take(3).Select(item => item.Message));
return exception.Message + "\n" + details;
}
return string.IsNullOrEmpty(exception.Message)
? "Сервер вернул ошибку " + exception.StatusCode + "."
: exception.Message;
}
private void SetBusy(bool busy, string status)
{
_busy = busy;
_loginButton.interactable = !busy;
_registerButton.interactable = !busy;
_serverUrl.interactable = !busy;
_userName.interactable = !busy;
_password.interactable = !busy;
if (status != null)
SetStatus(status, new Color(0.70f, 0.75f, 0.86f));
}
private void SetStatus(string text, Color color)
{
_status.text = text ?? string.Empty;
_status.color = color;
}
}
}