using System.Collections.Generic; using System.IO; using TMPro; using UnityEngine; using UnityEngine.UI; public class SongSelectManager : MonoBehaviour { [SerializeField] private Button tabAllBtn; [SerializeField] private Button tabOwnedBtn; [SerializeField] private RectTransform cardContainer; [SerializeField] private SongDetailPanel detailPanel; [SerializeField] private DownloadManager downloadManager; [SerializeField] private GameObject loadingOverlay; [SerializeField] private GameObject errorOverlay; [SerializeField] private TMP_Text errorText; [SerializeField] private TMP_FontAsset cardFont; private static readonly Color TabActive = Color.white; private static readonly Color TabInactive = new Color(0.6f, 0.6f, 0.6f); private static string CachePath => Path.Combine(Application.persistentDataPath, "songs_cache.json"); private List allSongs = new List(); private bool showingOwned = false; private void Start() { tabAllBtn .onClick.AddListener(() => SwitchTab(false)); tabOwnedBtn.onClick.AddListener(() => SwitchTab(true)); detailPanel.gameObject.SetActive(false); SetTabVisual(false); FetchSongs(); } private void SwitchTab(bool owned) { showingOwned = owned; SetTabVisual(owned); RefreshCards(); } private void SetTabVisual(bool owned) { ApplyTabColor(tabAllBtn, owned ? TabInactive : TabActive); ApplyTabColor(tabOwnedBtn, owned ? TabActive : TabInactive); } private static void ApplyTabColor(Button btn, Color c) { var colors = btn.colors; colors.normalColor = c; btn.colors = colors; } private void FetchSongs() { loadingOverlay.SetActive(true); errorOverlay .SetActive(false); downloadManager.FetchSongsList( onSuccess: list => { allSongs = list.songs; SaveCache(list); SongLibrary.Instance.ValidateWithFileSystem(downloadManager, list.songs); loadingOverlay.SetActive(false); RefreshCards(); }, onError: _ => { SongsList cached = LoadCache(); loadingOverlay.SetActive(false); if (cached != null) { allSongs = cached.songs; RefreshCards(); } else { errorOverlay.SetActive(true); errorText.text = "Failed to connect to server\nPlease check your internet connection"; } }); } public void RefreshCards() { for (int i = cardContainer.childCount - 1; i >= 0; i--) Destroy(cardContainer.GetChild(i).gameObject); List songs = showingOwned ? allSongs.FindAll(s => SongLibrary.Instance.IsSongDownloaded(s.id)) : allSongs; foreach (SongInfo song in songs) SpawnCard(song); } private void SpawnCard(SongInfo song) { bool downloaded = SongLibrary.Instance.IsSongDownloaded(song.id); var card = new GameObject(song.title); card.transform.SetParent(cardContainer, false); var le = card.AddComponent(); le.preferredHeight = 13f; le.flexibleWidth = 1f; var bg = card.AddComponent(); bg.color = new Color(1f, 1f, 1f, 0.06f); var btn = card.AddComponent