using UnityEngine; using UnityEngine.UI; using TMPro; using Ashwild.Network; using Ashwild.Player; namespace Ashwild.UI { /// /// Lets the player paste a friend's session code and connect to their room. Validates the /// code, launches the join through NetworkSessionManager, and mirrors the connection /// progress (connecting / error) from the PlayerEvents bus into an on-screen status line. /// public class JoinPanel : UIPanel { #region Serialized Fields [Header("Code")] [Tooltip("Where the player types/pastes the host's session code.")] [SerializeField] private TMP_InputField codeInput; [Header("Buttons")] [SerializeField] private Button joinButton; [SerializeField] private Button backButton; [Header("Feedback")] [Tooltip("Shows 'connecting…' / error messages. Optional.")] [SerializeField] private TMP_Text statusText; #endregion #region State /// /// True while a connection attempt is in flight (buttons locked, status shown). /// private bool isConnecting; #endregion #region Unity Lifecycle /// /// Wires the buttons and submit-on-enter; runs once. /// protected override void Awake() { base.Awake(); joinButton.onClick.AddListener(AttemptJoin); backButton.onClick.AddListener(() => UIManager.Instance.Back()); if (codeInput != null) codeInput.onSubmit.AddListener(_ => AttemptJoin()); } /// /// Subscribes to the session bus and resets the panel each time it is shown. /// public override void Show() { base.Show(); PlayerEvents.SessionJoining += HandleSessionJoining; PlayerEvents.SessionJoined += HandleSessionJoined; PlayerEvents.SessionError += HandleSessionError; ResetForInput(); } /// /// Unsubscribes — mirrors Show exactly so the panel never reacts while hidden. /// public override void Hide() { PlayerEvents.SessionJoining -= HandleSessionJoining; PlayerEvents.SessionJoined -= HandleSessionJoined; PlayerEvents.SessionError -= HandleSessionError; base.Hide(); } #endregion #region Event Handlers /// /// Connection attempt reached the transport — show progress. /// private void HandleSessionJoining(string code) => SetStatus($"Connexion à {code}…"); /// /// Connected to the host — the networked scene load takes over from here. /// private void HandleSessionJoined() => SetStatus("Connecté ! Chargement…"); /// /// Connection failed — surface the reason and re-enable input. /// private void HandleSessionError(string reason) { SetStatus(reason); isConnecting = false; SetInteractable(true); } #endregion #region Internal Helpers /// /// Validates the typed code and launches the join through NetworkSessionManager. /// private void AttemptJoin() { if (isConnecting) return; string code = codeInput != null ? codeInput.text.Trim() : string.Empty; if (string.IsNullOrEmpty(code)) { SetStatus("Entre un code de session."); return; } if (NetworkSessionManager.Instance == null) { Debug.LogError("[JoinPanel] NetworkSessionManager introuvable — la MenuScene doit contenir le NetworkManager.", this); SetStatus("Erreur interne (NetworkManager manquant)."); return; } GameSession.Mode = GameSession.LaunchMode.Join; GameSession.JoinCode = code; isConnecting = true; SetInteractable(false); SetStatus("Connexion…"); NetworkSessionManager.Instance.JoinSession(code); } /// /// Clears the status line and re-enables input — used each time the panel opens. /// private void ResetForInput() { isConnecting = false; SetInteractable(true); SetStatus(string.Empty); } /// /// Enables/disables the code field and join button during a connection attempt. /// private void SetInteractable(bool interactable) { if (codeInput != null) codeInput.interactable = interactable; if (joinButton != null) joinButton.interactable = interactable; } /// /// Writes a message to the optional status line. /// private void SetStatus(string message) { if (statusText != null) statusText.text = message; } #endregion } }