MomentItem.cs 10.9 KB
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.Video;

/**
 * 功能描述: 单条朋友圈+动态初始化 
 * @author wangQc
 * @date 2025/6/4 09:20
 */
public class MomentItem : MonoBehaviour
{
    public Image avatarImage;
    public TextMeshProUGUI usernameText;
    public TextMeshProUGUI contentText;

    
    public Transform imageGrid; // 父对象,用于图片缩略图排列
    public GameObject imagePrefab; // 小图预制体

    public Transform videoGrid; // 父对象
    public GameObject videoPrefab; // 视频预制体
    
    public TextMeshProUGUI from;
    public TextMeshProUGUI time;
    public Image likeIconImage;
    private string originLikeIcon;

    public Transform likeGrid; // 父对象,用于点赞emjoi排列
    public GameObject likePrefab; // 点赞emjoi预制体

    public TextMeshProUGUI likesText;
    public TextMeshProUGUI likedEmoji;
    
    private string originLikesText;

    public TextMeshProUGUI commentsText;
    
    public DanmakuManager danmakuManager;
    
    public RectTransform checkRectTransform; // 你要检测的 UI 元素
    private RectTransform scrollViewRectTransform;
    private ScrollRect scrollRect;

    void Awake()
    { 
        scrollViewRectTransform = checkRectTransform.parent.parent.parent.parent.parent.parent.parent as RectTransform;
        scrollRect = scrollViewRectTransform.GetComponent<ScrollRect>();
    }

    void Update()
    {

        // if (scrollRect.velocity.sqrMagnitude > 0.01f)
        // {
        //     bool isOver = IsUIOverlapping(checkRectTransform,scrollViewRectTransform);
        //     if (!isOver)
        //     {
        //         StartCoroutine(ImageLoader.LoadImage(originLikeIcon, likeIconImage));
        //         likesText.text = originLikesText;
        //         likeIconImage.gameObject.SetActive(true);
        //     }
        // }
    }
    
    public bool IsUIOverlapping(RectTransform rectA, RectTransform rectB)
    {
        Vector3[] cornersA = new Vector3[4];
        Vector3[] cornersB = new Vector3[4];

        rectA.GetWorldCorners(cornersA);
        rectB.GetWorldCorners(cornersB);

        // 打印 A 的四个角(左下、左上、右上、右下)
        // Debug.Log($"A corners:\n" +
        //           $"左下: {cornersA[0]}\n" +
        //           $"左上:    {cornersA[1]}\n" +
        //           $"右上:   {cornersA[2]}\n" +
        //           $"右下:{cornersA[3]}");
        //
        // Debug.Log($"B corners:\n" +
        //           $"左下: {cornersB[0]}\n" +
        //           $"左上:    {cornersB[1]}\n" +
        //           $"右上:   {cornersB[2]}\n" +
        //           $"右下:{cornersB[3]}");
        
        return geRect(cornersA).Overlaps(geRect(cornersB));
    }

    public Rect geRect(Vector3[] corners)
    {
        // 获取最小和最大点
        Vector3 min = corners[0];
        Vector3 max = corners[0];

        for (int i = 1; i < 4; i++)
        {
            min = Vector3.Min(min, corners[i]);
            max = Vector3.Max(max, corners[i]);
        }

        // 构建 Rect(在世界坐标系下)
        return  new Rect(min.x, min.y, max.x - min.x, max.y - min.y);

    }



    public int Setup(Moment moment,List<Like> likeList,string likeIcon,string logo,int momentCount)
    {
        //计算单条朋友圈所占高度
        //每行字50
        int line = 50;
        //图片、视频400
        int media = 400;
        int momentHeight = 0;
        usernameText.text = moment.username;
        momentHeight+= line;
        
        contentText.text = moment.text;
        //计算文本的行数,每行30个字
        int textLine = (int)Math.Ceiling((double)moment.text.Length / 30);
        momentHeight+= textLine*line;
        
        from.text = moment.from;
        time.text = moment.time;
        StartCoroutine(ImageLoader.LoadImage(likeIcon, likeIconImage));
        originLikeIcon = likeIcon;
        momentHeight+= line;

        
        StartCoroutine(ImageLoader.LoadImage(moment.avatarUrl, avatarImage));
        
        Button likeIconBtn = likeIconImage.GetComponent<Button>();
        likeIconBtn.onClick.AddListener(() =>
        {
            likeGrid.gameObject.SetActive(true);
        });
        
        
        Button likedEmojiBtn = likedEmoji.GetComponent<Button>();
        likedEmojiBtn.onClick.AddListener(() =>
        {
            //显示点赞Icon
            likeIconImage.gameObject.SetActive(true);
            
            likedEmoji.gameObject.SetActive(false);
            likedEmoji.text = "";
            likeGrid.gameObject.SetActive(true);
        });


        // 清空之前的图片
        foreach (Transform child in imageGrid)
            Destroy(child.gameObject);
        foreach (string url in moment.imageUrls)
        {
            imageGrid.gameObject.SetActive(true);
            videoGrid.gameObject.SetActive(false);

            GameObject imgObj = Instantiate(imagePrefab, imageGrid);
            Image img = imgObj.GetComponent<Image>();
            StartCoroutine(ImageLoader.LoadImage(url, img));
            Transform child = imgObj.transform.GetChild(0);
            child.DOScale(0.45f, 2f).SetLoops(-1, LoopType.Yoyo).SetEase(Ease.InOutSine);
            
            Button btn = imgObj.GetComponent<Button>();
            btn.onClick.AddListener(() => ImageViewerManager.Instance.ShowImage(url,moment.text,logo,moment.time));
        }
        //一行两张图片,计算有几行
        momentHeight+=  (int)Math.Ceiling((double)moment.imageUrls.Count / 2) * media;

        
        
        foreach (Transform child in videoGrid)
            Destroy(child.gameObject);
        //判断是否有视频
        if (!string.IsNullOrWhiteSpace(moment.video))
        {
            //有视频就没有图
            imageGrid.gameObject.SetActive(false);
            videoGrid.gameObject.SetActive(true);
            // 1. 实例化
            GameObject obj = Instantiate(videoPrefab, videoGrid);

            // 2. 获取组件
            RawImage rawImage = obj.GetComponentInChildren<RawImage>();
            VideoPlayer videoPlayer = obj.GetComponentInChildren<VideoPlayer>();

            // 3. 创建新的 RenderTexture(每个视频独立)
            RenderTexture renderTex = new RenderTexture(1920, 1080, 0);
            renderTex.Create();

            // 4. 绑定到 RawImage 和 VideoPlayer
            videoPlayer.targetTexture = renderTex;
            rawImage.texture = renderTex;

            // 5. 设置视频源
            videoPlayer.source = VideoSource.Url;
            videoPlayer.url = moment.video;

            // 6. 播放
            videoPlayer.Play();
            
            Button btn = obj.GetComponent<Button>();
            btn.onClick.AddListener(() => VideoViewerManager.Instance.ShowVideo(moment));
            
            momentHeight+=  media;
        }
        



        //点赞图片以及文字初始化
        foreach (Transform child in likeGrid)
            Destroy(child.gameObject);
        foreach (Like like in likeList)
        {
            GameObject evaluateObj = Instantiate(likePrefab, likeGrid);
            var evaluateTextMeshPro = evaluateObj.GetComponent<TextMeshProUGUI>();
            evaluateTextMeshPro.text = like.icon;
            
            Button evaluateBtn = evaluateObj.GetComponent<Button>();
            evaluateBtn.onClick.AddListener(() =>
            {
                Debug.Log(like.bullet);
                //埋点+显示当前点赞人数
                var buryPointInfos = new BuryPointManager.BuryPointInfos();
                buryPointInfos.eventId = "button_click";
                var buryPointClickParam = new BuryPointManager.BuryPointClickParam
                {
                    page = "FriendCircle",
                };
                buryPointClickParam.buttonId = $"moment_{momentCount}_like_{like.icon}";
                buryPointClickParam.buttonText = "点赞";
                buryPointInfos.remark = $"第{momentCount}条朋友圈点赞,点赞icon:{like.icon}";
                buryPointInfos.@params = buryPointClickParam;
                BuryPointManager.Instance.BuryPoint(buryPointInfos, (res) =>
                {
                    
                    BuryPointManager.RequestInfos<long> requestInfos = JsonUtility.FromJson<BuryPointManager.RequestInfos<long>>(res);
                    // Debug.Log("埋点请求成功:"+res);
                    
                    //发送弹幕(竖屏)
                    danmakuManager.AddDanmakuBatch(new List<string>
                    {
                        like.bullet,
                        like.icon + " " + like.icon + " " + like.icon,
                        $"第{requestInfos.data}位"

                    },0.4f,2);
   
                }, (err) =>
                {
                    Debug.Log("埋点请求报错:"+err);
                });
                
                //隐藏点赞Icon
                likeIconImage.gameObject.SetActive(false);
                //显示已经点赞的emoji标签
                likedEmoji.text = like.icon;
                likedEmoji.gameObject.SetActive(true);

                likeGrid.gameObject.SetActive(false);
                
                //增加点赞名字
                var names = likesText.text.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(n => n.Trim())
                    .ToList(); // ✅ 转成 List<string>
                string target = "一个不愿透露姓名的游客";
                if (!names.Contains(target))
                {
                    names.Add(target);
                }
                likesText.text = string.Join(", ", names);
            });
        }
        
        momentHeight+= line;

        likesText.text = string.Join(", ", moment.likeNameList);
        originLikesText = likesText.text;
        
        commentsText.text = "";
        LoadComments(moment.comments);
        momentHeight+= moment.comments.Count*line;

        return momentHeight+200;
    }
    

    public void LoadComments(List<CommentData> comments)
    {
        string nameHex = "576B95"; // 名称和冒号颜色
        StringBuilder sb = new StringBuilder();

        foreach (var comment in comments)
        {
            string commentLine;
            if (!string.IsNullOrEmpty(comment.replier))
            {
                // 有回复者
                commentLine = $"<b><color=#{nameHex}>{comment.commenter}</color></b> 回复 <b><color=#{nameHex}>{comment.replier}</color></b><color=#{nameHex}>:</color>{comment.content}";
            }
            else
            {
                // 普通评论
                commentLine = $"<b><color=#{nameHex}>{comment.commenter}</color></b><color=#{nameHex}>:</color> {comment.content}";
            }

            sb.AppendLine(commentLine); // 添加换行
        }

        commentsText.text = sb.ToString();
    }

}