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

246 lines
9.7 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.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using Vanguard.Api;
using Vanguard.Auth;
using Vanguard.State;
namespace Vanguard.UI
{
/// <summary>Главный экран после входа: профиль, балансы и заглушки разделов.</summary>
public sealed class MetaView
{
private readonly AuthService _auth;
private readonly PlayerState _player;
private readonly Action _onLoggedOut;
private readonly RectTransform _root;
private readonly Text _playerName;
private readonly Text _onboarding;
private readonly Text _gold;
private readonly Text _dust;
private readonly Text _tokens;
private readonly Text _ranked;
private readonly Text _casual;
private readonly Text _record;
private readonly Text _status;
private readonly Button _logout;
private readonly Button _onboardingButton;
private bool _refreshing;
public MetaView(
Transform parent,
AuthService auth,
PlayerState player,
Action onLoggedOut)
{
_auth = auth;
_player = player;
_onLoggedOut = onLoggedOut;
_root = UiKit.CreatePanel(parent, "MetaScreen", new Color(0.035f, 0.045f, 0.065f, 1f));
var top = UiKit.CreatePanel(_root, "TopBar", new Color(0.07f, 0.085f, 0.115f, 1f));
var topRect = top;
topRect.anchorMin = new Vector2(0f, 1f);
topRect.anchorMax = new Vector2(1f, 1f);
topRect.pivot = new Vector2(0.5f, 1f);
topRect.anchoredPosition = Vector2.zero;
topRect.sizeDelta = new Vector2(0f, 92f);
UiKit.AddHorizontalLayout(top, 22, 16);
var brand = UiKit.CreateText(
top, "Brand", "VANGUARD", 34, new Color(0.86f, 0.90f, 1f), TextAnchor.MiddleLeft);
brand.fontStyle = FontStyle.Bold;
UiKit.SetPreferredHeight(brand, 48f, 0f);
_playerName = UiKit.CreateText(
top, "PlayerName", "…", 20, new Color(0.70f, 0.76f, 0.90f), TextAnchor.MiddleLeft);
UiKit.SetPreferredHeight(_playerName, 40f);
_logout = UiKit.CreateButton(top, "Logout", "Выйти", OnLogoutClicked, 18);
UiKit.SetPreferredHeight(_logout, 42f, 0f);
var content = UiKit.CreatePanel(_root, "Content", new Color(0.035f, 0.045f, 0.065f, 0f));
var contentRect = content;
contentRect.anchorMin = Vector2.zero;
contentRect.anchorMax = Vector2.one;
contentRect.offsetMin = new Vector2(48f, 36f);
contentRect.offsetMax = new Vector2(-48f, -116f);
UiKit.AddVerticalLayout(contentRect, 12, 16);
var welcome = UiKit.CreateText(
content, "Welcome", "Личный кабинет", 38, Color.white, TextAnchor.MiddleLeft);
UiKit.SetPreferredHeight(welcome, 56f);
_onboarding = UiKit.CreateText(
content, "Onboarding", string.Empty, 18,
new Color(1f, 0.76f, 0.38f), TextAnchor.MiddleLeft);
UiKit.SetPreferredHeight(_onboarding, 28f);
var stats = UiKit.CreatePanel(content, "Stats", new Color(0.07f, 0.085f, 0.115f, 1f));
UiKit.SetPreferredHeight(stats, 130f);
UiKit.AddHorizontalLayout(stats, 18, 14);
_gold = AddStat(stats, "Gold");
_dust = AddStat(stats, "Пыль");
_tokens = AddStat(stats, "Токены");
_ranked = AddStat(stats, "Ranked MMR");
_casual = AddStat(stats, "Casual MMR");
var actions = UiKit.CreatePanel(content, "Actions", new Color(0.07f, 0.085f, 0.115f, 1f));
UiKit.SetPreferredHeight(actions, 96f);
UiKit.AddHorizontalLayout(actions, 18, 14);
AddAction(actions, "Коллекция", OnCollectionClicked);
AddAction(actions, "Колоды", OnDecksClicked);
AddAction(actions, "Магазин", OnStoreClicked);
AddAction(actions, "В бой", OnPlayClicked);
var lower = UiKit.CreatePanel(content, "Lower", new Color(0.07f, 0.085f, 0.115f, 1f));
UiKit.SetPreferredHeight(lower, 220f, 1f);
UiKit.AddVerticalLayout(lower, 20, 8);
_record = UiKit.CreateText(
lower, "Record", string.Empty, 20,
new Color(0.72f, 0.78f, 0.92f), TextAnchor.MiddleLeft);
UiKit.SetPreferredHeight(_record, 28f);
_status = UiKit.CreateText(
lower, "Status", string.Empty, 18,
new Color(0.62f, 0.68f, 0.82f), TextAnchor.UpperLeft);
UiKit.SetPreferredHeight(_status, 70f);
_onboardingButton = UiKit.CreateButton(
lower, "OnboardingButton", "Выбрать триал-деку", OnOnboardingClicked, 20);
UiKit.SetPreferredHeight(_onboardingButton, 46f);
_player.Changed += UpdateTexts;
_root.gameObject.SetActive(false);
}
public void Show()
{
UiKit.SetActive(_root, true);
UpdateTexts();
_ = RefreshAsync();
}
public void Hide() => UiKit.SetActive(_root, false);
private static Text AddStat(Transform parent, string caption)
{
var card = UiKit.CreatePanel(parent, "Stat_" + caption, new Color(0.09f, 0.11f, 0.15f, 1f));
UiKit.AddVerticalLayout(card, 12, 4);
var element = card.gameObject.AddComponent<LayoutElement>();
element.flexibleWidth = 1f;
element.preferredHeight = 100f;
var label = UiKit.CreateText(
card, "Caption", caption, 16, new Color(0.58f, 0.65f, 0.78f));
UiKit.SetPreferredHeight(label, 22f);
var value = UiKit.CreateText(
card, "Value", "—", 30, Color.white);
value.fontStyle = FontStyle.Bold;
UiKit.SetPreferredHeight(value, 40f);
return value;
}
private static Button AddAction(Transform parent, string caption, Action onClick)
{
var button = UiKit.CreateButton(parent, "Action_" + caption, caption, () => onClick(), 20);
var element = button.gameObject.AddComponent<LayoutElement>();
element.flexibleWidth = 1f;
element.preferredHeight = 56f;
return button;
}
private async Task RefreshAsync()
{
if (_refreshing)
return;
_refreshing = true;
SetStatus("Обновляем профиль…", new Color(0.62f, 0.68f, 0.82f));
try
{
await _auth.RefreshMeAsync();
SetStatus("Профиль обновлён.", new Color(0.45f, 0.85f, 0.55f));
}
catch (ApiException exception) when (exception.StatusCode == 401)
{
_onLoggedOut();
}
catch (Exception exception)
{
Debug.LogException(exception);
SetStatus("Не удалось обновить профиль. Сервер недоступен?", new Color(1f, 0.60f, 0.45f));
}
finally
{
_refreshing = false;
}
}
private void UpdateTexts()
{
_playerName.text = string.IsNullOrEmpty(_player.UserName)
? "…"
: _player.UserName;
_gold.text = _player.Gold.ToString();
_dust.text = _player.Dust.ToString();
_tokens.text = _player.Tokens.ToString();
_ranked.text = _player.RankedMmr.ToString();
_casual.text = _player.CasualMmr.ToString();
_record.text = "Матчей: " + _player.Matches + " · побед: " + _player.Wins
+ " · XP: " + _player.Xp;
_onboarding.text = _player.OnboardingCompleted
? "Онбординг завершён: " + (_player.SelectedTrialDeckId ?? "—")
: "Онбординг не завершён: выберите стартовую триал-деку.";
_onboardingButton.gameObject.SetActive(!_player.OnboardingCompleted);
}
private void SetStatus(string text, Color color)
{
_status.text = text ?? string.Empty;
_status.color = color;
}
private void OnCollectionClicked() =>
SetStatus("Коллекция и разбор карт — следующий экран.", new Color(0.70f, 0.76f, 0.90f));
private void OnDecksClicked() =>
SetStatus("Декбилдер и список колод — следующий экран.", new Color(0.70f, 0.76f, 0.90f));
private void OnStoreClicked() =>
SetStatus("Магазин и открытие бустеров — следующий экран.", new Color(0.70f, 0.76f, 0.90f));
private void OnPlayClicked()
{
SetStatus(
_player.OnboardingCompleted
? "Очередь подключим после выбора колоды."
: "Сначала завершите онбординг.",
new Color(1f, 0.76f, 0.38f));
}
private void OnOnboardingClicked() =>
SetStatus("Выбор триал-деки подключим следующим шагом.", new Color(1f, 0.76f, 0.38f));
private async void OnLogoutClicked()
{
_logout.interactable = false;
await _auth.LogoutAsync();
_logout.interactable = true;
_onLoggedOut();
}
}
}