using TMPro; using UnityEngine; namespace BrewMonster.Scripts.ChatUI { /// /// Controls typing preview visibility/content and keyboard-anchored position. /// Kept standalone so other chat/input UIs can reuse the same behavior. /// [System.Serializable] public class TypingPreviewController { [Tooltip("Root của box xem trước nội dung đang gõ.")] [SerializeField] private GameObject typingPreviewRoot; [Tooltip("Text hiển thị nội dung đang gõ realtime.")] [SerializeField] private TMP_InputField typingPreviewText; [Tooltip("Rect của preview box để neo theo keyboard.")] [SerializeField] private RectTransform typingPreviewRect; [Tooltip("Khoảng cách dọc cộng thêm cho preview box.")] [SerializeField] private float previewVerticalOffset = 8f; private Vector2 _baseAnchoredPos; private bool _cachedAnchor; public void CacheInitialAnchor() { if (_cachedAnchor) return; if (typingPreviewRect != null) _baseAnchoredPos = typingPreviewRect.anchoredPosition; _cachedAnchor = true; } public void ApplyKeyboardOffset(float yOffset) { if (typingPreviewRect == null) return; CacheInitialAnchor(); var previewPos = _baseAnchoredPos; previewPos.y += yOffset + previewVerticalOffset; typingPreviewRect.anchoredPosition = previewPos; } public void UpdatePreview(bool isInputFocused, string body) { if (typingPreviewRoot == null || typingPreviewText == null) return; string previewBody = body ?? string.Empty; bool keyboardVisible = IsMobileKeyboardVisible(); bool shouldShow = keyboardVisible && isInputFocused; typingPreviewRoot.SetActive(shouldShow); if (shouldShow) typingPreviewText.text = previewBody; } bool IsMobileKeyboardVisible() { if (!Application.isMobilePlatform) return false; return GetVisibleKeyboardHeight() > 0f || TouchScreenKeyboard.visible; } float GetVisibleKeyboardHeight() { if (!TouchScreenKeyboard.visible) return 0f; Rect area = TouchScreenKeyboard.area; return area.height > 0f ? area.height : 0f; } } }