219 lines
7.8 KiB
C#
219 lines
7.8 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Threading.Tasks;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
using Vanguard.Api;
|
||
using Vanguard.Api.Contracts;
|
||
using Vanguard.Auth;
|
||
using Vanguard.Meta;
|
||
|
||
namespace Vanguard.UI
|
||
{
|
||
/// <summary>История матчей в Lobby и вход в реплей.</summary>
|
||
public sealed class HistoryView
|
||
{
|
||
private readonly MetaService _meta;
|
||
private readonly AuthService _auth;
|
||
private readonly Action _onBack;
|
||
|
||
private readonly RectTransform _root;
|
||
private readonly Text _status;
|
||
private readonly RectTransform _content;
|
||
private readonly ReplayView _replay;
|
||
private bool _loading;
|
||
|
||
public HistoryView(
|
||
Transform parent,
|
||
MetaService meta,
|
||
AuthService auth,
|
||
Action onBack)
|
||
{
|
||
_meta = meta;
|
||
_auth = auth;
|
||
_onBack = onBack;
|
||
|
||
_root = UiKit.CreatePanel(parent, "HistoryScreen", new Color(0.018f, 0.03f, 0.06f, 0.96f));
|
||
|
||
var top = UiKit.CreatePanel(_root, "TopBar", new Color(0.06f, 0.08f, 0.13f, 1f));
|
||
top.anchorMin = new Vector2(0f, 1f);
|
||
top.anchorMax = new Vector2(1f, 1f);
|
||
top.pivot = new Vector2(0.5f, 1f);
|
||
top.anchoredPosition = Vector2.zero;
|
||
top.sizeDelta = new Vector2(0f, 88f);
|
||
UiKit.AddHorizontalLayout(top, 22, 16);
|
||
|
||
var back = UiKit.CreateButton(top, "Back", "← В лобби", () => _onBack(), 18);
|
||
UiKit.SetPreferredHeight(back, 44f, 0f);
|
||
|
||
var title = UiKit.CreateText(top, "Title", "История матчей", 32, Color.white, TextAnchor.MiddleLeft);
|
||
title.fontStyle = FontStyle.Bold;
|
||
UiKit.SetPreferredHeight(title, 46f);
|
||
|
||
var hint = UiKit.CreateText(
|
||
top, "Hint", "Только ваши матчи · реплей доступен участникам", 16,
|
||
new Color(0.60f, 0.68f, 0.84f), TextAnchor.MiddleRight);
|
||
UiKit.SetPreferredHeight(hint, 36f);
|
||
|
||
var body = UiKit.CreatePanel(_root, "Body", new Color(0f, 0f, 0f, 0f));
|
||
body.anchorMin = Vector2.zero;
|
||
body.anchorMax = Vector2.one;
|
||
body.offsetMin = new Vector2(44f, 30f);
|
||
body.offsetMax = new Vector2(-44f, -110f);
|
||
UiKit.AddVerticalLayout(body, 8, 10);
|
||
|
||
var scroll = UiKit.CreateScrollView(body, "HistoryScroll", out _content, 8f);
|
||
var scrollElement = scroll.gameObject.AddComponent<LayoutElement>();
|
||
scrollElement.flexibleHeight = 1f;
|
||
scrollElement.minHeight = 200f;
|
||
|
||
_status = UiKit.CreateText(
|
||
body, "Status", string.Empty, 18,
|
||
new Color(0.62f, 0.68f, 0.82f), TextAnchor.MiddleLeft);
|
||
UiKit.SetPreferredHeight(_status, 34f);
|
||
|
||
_replay = new ReplayView(_root, _meta, HideReplay);
|
||
_root.gameObject.SetActive(false);
|
||
}
|
||
|
||
public void Show()
|
||
{
|
||
UiKit.SetActive(_root, true);
|
||
_replay.Hide();
|
||
_ = LoadAsync();
|
||
}
|
||
|
||
public void Hide()
|
||
{
|
||
_replay.Hide();
|
||
UiKit.SetActive(_root, false);
|
||
}
|
||
|
||
private async Task LoadAsync()
|
||
{
|
||
if (_loading)
|
||
return;
|
||
|
||
_loading = true;
|
||
SetStatus("Загружаем историю…", new Color(0.62f, 0.68f, 0.82f));
|
||
ClearChildren(_content);
|
||
|
||
try
|
||
{
|
||
await _auth.EnsureAccessAsync();
|
||
var history = await _meta.GetHistoryAsync();
|
||
if (_root == null || !_root.gameObject.activeSelf)
|
||
return;
|
||
|
||
Build(history.Items);
|
||
SetStatus(
|
||
history.Items == null || history.Items.Count == 0
|
||
? "Матчей пока нет."
|
||
: "Матчей: " + history.Items.Count + ".",
|
||
new Color(0.62f, 0.68f, 0.82f));
|
||
}
|
||
catch (ApiException exception)
|
||
{
|
||
SetStatus(exception.Message, new Color(1f, 0.55f, 0.45f));
|
||
}
|
||
catch (Exception exception)
|
||
{
|
||
Debug.LogException(exception);
|
||
SetStatus("Не удалось загрузить историю.", new Color(1f, 0.55f, 0.45f));
|
||
}
|
||
finally
|
||
{
|
||
_loading = false;
|
||
}
|
||
}
|
||
|
||
private void Build(IReadOnlyList<MatchHistoryDto> items)
|
||
{
|
||
ClearChildren(_content);
|
||
if (items == null || items.Count == 0)
|
||
return;
|
||
|
||
foreach (var item in items)
|
||
AddRow(item);
|
||
}
|
||
|
||
private void AddRow(MatchHistoryDto item)
|
||
{
|
||
var row = UiKit.CreatePanel(_content, "Match_" + item.MatchId, new Color(0.07f, 0.09f, 0.14f, 1f));
|
||
var rowElement = row.gameObject.AddComponent<LayoutElement>();
|
||
rowElement.preferredHeight = 96f;
|
||
UiKit.AddHorizontalLayout(row, 14, 14);
|
||
|
||
var info = UiKit.CreatePanel(row, "Info", new Color(0f, 0f, 0f, 0f));
|
||
var infoElement = info.gameObject.AddComponent<LayoutElement>();
|
||
infoElement.flexibleWidth = 1f;
|
||
infoElement.preferredHeight = 64f;
|
||
UiKit.AddVerticalLayout(info, 0, 2);
|
||
|
||
var opponent = UiKit.CreateText(
|
||
info,
|
||
"Opponent",
|
||
(item.Result == "win" ? "Победа" : item.Result == "loss" ? "Поражение" : "Ничья")
|
||
+ " против " + item.OpponentName,
|
||
21,
|
||
item.Result == "win" ? new Color(0.45f, 0.85f, 0.55f) : new Color(1f, 0.62f, 0.48f),
|
||
TextAnchor.MiddleLeft);
|
||
opponent.fontStyle = FontStyle.Bold;
|
||
UiKit.SetPreferredHeight(opponent, 28f);
|
||
|
||
var detail = UiKit.CreateText(
|
||
info,
|
||
"Detail",
|
||
item.Mode + " · " + item.FinishReason + " · "
|
||
+ item.PlayedAt.ToLocalTime().ToString("dd.MM.yyyy HH:mm"),
|
||
16,
|
||
new Color(0.60f, 0.68f, 0.84f),
|
||
TextAnchor.MiddleLeft);
|
||
UiKit.SetPreferredHeight(detail, 24f);
|
||
|
||
var rewards = UiKit.CreateText(
|
||
row,
|
||
"Rewards",
|
||
"Gold " + item.Gold + " · XP " + item.Xp
|
||
+ "\nMMR " + item.MmrBefore + " → " + item.MmrAfter,
|
||
16,
|
||
new Color(0.72f, 0.78f, 0.92f));
|
||
var rewardsElement = rewards.gameObject.AddComponent<LayoutElement>();
|
||
rewardsElement.preferredWidth = 210f;
|
||
rewardsElement.preferredHeight = 56f;
|
||
|
||
var replay = UiKit.CreateButton(
|
||
row,
|
||
"Replay",
|
||
item.ReplayAvailable ? "Реплей" : "Нет реплея",
|
||
() => _replay.Show(item.MatchId),
|
||
17);
|
||
replay.interactable = item.ReplayAvailable;
|
||
var replayElement = replay.gameObject.AddComponent<LayoutElement>();
|
||
replayElement.preferredWidth = 130f;
|
||
replayElement.preferredHeight = 46f;
|
||
replayElement.flexibleWidth = 0f;
|
||
}
|
||
|
||
private void HideReplay()
|
||
{
|
||
_replay.Hide();
|
||
}
|
||
|
||
private void SetStatus(string text, Color color)
|
||
{
|
||
if (_status == null)
|
||
return;
|
||
|
||
_status.text = text ?? string.Empty;
|
||
_status.color = color;
|
||
}
|
||
|
||
private static void ClearChildren(Transform parent)
|
||
{
|
||
for (var i = parent.childCount - 1; i >= 0; i--)
|
||
UnityEngine.Object.Destroy(parent.GetChild(i).gameObject);
|
||
}
|
||
}
|
||
}
|