using System; using System.Threading.Tasks; using UnityEngine; using UnityEngine.UI; using Vanguard.Api; using Vanguard.App; using Vanguard.Auth; using Vanguard.State; namespace Vanguard.UI { /// /// Главный экран после входа: профиль и балансы, вход в бой/колоды/магазин, /// заглушки разделов без серверной части и гамбургер-меню. /// public sealed class LobbyView : IDisposable { public const string RootName = "LobbyScreen"; private const float Margin = 24f; private const float TopHeight = 96f; private const float LeftWidth = 560f; private const float RightWidth = 336f; private const float Gutter = 16f; private const float ContentTop = 112f; private const float BottomMargin = 24f; private const float BalanceHeight = 88f; private static readonly Color PanelFill = new Color(0.024f, 0.058f, 0.15f, 0.92f); private static readonly Color PanelFillSoft = new Color(0.035f, 0.08f, 0.19f, 0.55f); private static readonly Color Border = new Color(0.18f, 0.49f, 1f, 0.55f); private static readonly Color BorderStrong = new Color(0.34f, 0.72f, 1f, 0.9f); private static readonly Color TextPrimary = new Color(0.88f, 0.93f, 1f); private static readonly Color TextMuted = new Color(0.58f, 0.69f, 0.88f); private static readonly Color TextDim = new Color(0.44f, 0.55f, 0.75f); private static readonly Color Accent = new Color(0.37f, 0.69f, 1f); private readonly AuthService _auth; private readonly PlayerState _player; private readonly Action _onLoggedOut; private readonly Action _onStore; private readonly HamburgerMenu _menu; private readonly StatusTicker _ticker; private readonly RectTransform _root; private Text _avatar; private Text _playerName; private Text _mmr; private Text _gold; private Text _dust; private Text _tokens; private Text _status; private bool _disposed; private bool _refreshing; public LobbyView( Transform parent, AppConfig config, AuthService auth, PlayerState player, Action onLoggedOut, Action onBattle, Action onDecks, Action onStore, Action onHistory, Action onRating, Action onCommunity) { _auth = auth; _player = player; _onLoggedOut = onLoggedOut; _onStore = onStore; _root = UiKit.CreatePanel(parent, RootName, new Color(0f, 0f, 0f, 0f)); _root.GetComponent().raycastTarget = false; var top = TopBar(out _avatar, out _playerName, out _mmr); AddTopAction(top, "Rating", "Рейтинг", -312f, 180f, () => onRating(), LobbyIcon.Chart); AddTopAction(top, "Community", "Сообщество", -96f, 200f, () => onCommunity(), LobbyIcon.Friends); BuildActions(onBattle, onDecks, onStore); BuildMissions(out _status); BuildBalances(out _gold, out _dust, out _tokens); BuildChat(); BuildFriends(); _menu = new HamburgerMenu(_root, config, onLoggedOut, onHistory); _ticker = _root.gameObject.AddComponent(); _ticker.Hide = () => SetStatus(string.Empty); _player.Changed += UpdateTexts; Loc.LanguageChanged += UpdateTexts; UpdateTexts(); _root.gameObject.SetActive(false); } public bool IsMenuOpen => _menu != null && _menu.IsOpen; public void CloseMenu() { if (_menu != null) _menu.Close(); } public void Show() { UiKit.SetActive(_root, true); UpdateTexts(); _ = RefreshAsync(); } public void Hide() => UiKit.SetActive(_root, false); public void Dispose() { if (_disposed) return; _disposed = true; _player.Changed -= UpdateTexts; Loc.LanguageChanged -= UpdateTexts; } // ------------------------------------------------------------ топбар private RectTransform TopBar(out Text avatar, out Text playerName, out Text mmr) { var top = Surface(_root, "TopBar", new Color(0.012f, 0.03f, 0.08f, 0.94f), Border, 1, 0); top.anchorMin = new Vector2(0f, 1f); top.anchorMax = new Vector2(1f, 1f); top.pivot = new Vector2(0.5f, 1f); top.offsetMin = new Vector2(Margin, -TopHeight); top.offsetMax = new Vector2(-Margin, 0f); var avatarRect = Surface( top, "Avatar", new Color(0.05f, 0.13f, 0.3f, 0.95f), BorderStrong, 2, 14); avatarRect.anchorMin = new Vector2(0f, 0.5f); avatarRect.anchorMax = new Vector2(0f, 0.5f); avatarRect.pivot = new Vector2(0f, 0.5f); avatarRect.sizeDelta = new Vector2(64f, 64f); avatarRect.anchoredPosition = new Vector2(20f, 0f); avatar = UiKit.CreateText(avatarRect, "Initials", "?", 26, TextPrimary); avatar.fontStyle = FontStyle.Bold; UiKit.Stretch(avatar.rectTransform); UiKit.MakeLiteral(avatar); playerName = UiKit.CreateText( top, "PlayerName", "…", 22, TextPrimary, TextAnchor.MiddleLeft); playerName.fontStyle = FontStyle.Bold; var nameRect = playerName.rectTransform; nameRect.anchorMin = new Vector2(0f, 0.5f); nameRect.anchorMax = new Vector2(0f, 0.5f); nameRect.pivot = new Vector2(0f, 0.5f); nameRect.sizeDelta = new Vector2(420f, 30f); nameRect.anchoredPosition = new Vector2(104f, 14f); UiKit.MakeLiteral(playerName); mmr = UiKit.CreateText( top, "Mmr", string.Empty, 14, TextMuted, TextAnchor.MiddleLeft); var mmrRect = mmr.rectTransform; mmrRect.anchorMin = new Vector2(0f, 0.5f); mmrRect.anchorMax = new Vector2(0f, 0.5f); mmrRect.pivot = new Vector2(0f, 0.5f); mmrRect.sizeDelta = new Vector2(460f, 22f); mmrRect.anchoredPosition = new Vector2(104f, -16f); UiKit.MakeLiteral(mmr); var season = UiKit.CreateText( top, "Season", "Сезон — скоро", 14, TextDim, TextAnchor.MiddleCenter); var seasonRect = season.rectTransform; seasonRect.anchorMin = new Vector2(0.5f, 0.5f); seasonRect.anchorMax = new Vector2(0.5f, 0.5f); seasonRect.sizeDelta = new Vector2(280f, 30f); seasonRect.anchoredPosition = Vector2.zero; return top; } private void AddTopAction( RectTransform parent, string name, string label, float rightOffset, float width, Action onClick, Action icon) { var buttonRect = Surface( parent, name, new Color(0.035f, 0.09f, 0.21f, 0.85f), Border, 1, 12); buttonRect.anchorMin = new Vector2(1f, 0.5f); buttonRect.anchorMax = new Vector2(1f, 0.5f); buttonRect.pivot = new Vector2(1f, 0.5f); buttonRect.sizeDelta = new Vector2(width, 52f); buttonRect.anchoredPosition = new Vector2(rightOffset, 0f); var image = buttonRect.GetComponent(); image.raycastTarget = true; var button = buttonRect.gameObject.AddComponent