205 lines
7.1 KiB
C#
205 lines
7.1 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|