lcy
2025-12-03 b9a6e7e896b451e9c915e782a1789b2afe079cc9
Main/System/Chat/ChatWin.cs
@@ -1,279 +1,514 @@
//--------------------------------------------------------
//    [Author]:           玩个游戏
//    [  Date ]:           Monday, April 09, 2018
//--------------------------------------------------------
using System;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ChatWin : UIBase
{
    [SerializeField, Header("锁定当前区域比例"), Range(0, 1)] float m_Percent = 0.3f;
    [SerializeField] ButtonEx btnSetting;
    [SerializeField] ButtonEx btnClose;
    public class ChatWin : UIBase
    [SerializeField] ScrollerController scrChatTab;
    [SerializeField] ChatPlayerMineCell m_ChatMineCell;
    [SerializeField] ChatPlayerOtherCell m_ChatOtherCell;
    [SerializeField] ChatSysCell m_ChatSysCell;
    [SerializeField] Transform transInput;
    [SerializeField] InputField inputChat;
    [SerializeField] ButtonEx btnSendChat;
    [SerializeField] ImageEx imgSendChat;
    [SerializeField] TextEx txtSendChat;
    [SerializeField] ScrollerController scrWorld;
    [SerializeField] ScrollerController scrGuild;
    private int unreadMsgCount = 0;
    [SerializeField] ButtonEx btnNewMsgTip;
    [SerializeField] TextEx txtNewMsgTip;
    [SerializeField, Header("聊天弹幕设置")] Transform transSettings;
    [SerializeField] ClickScreenOtherSpace clickScreenOtherSpace;
    bool isSettingOpen = false;
    [SerializeField] ChatSettingButton btnWorldSetting;
    [SerializeField] ChatSettingButton btnGuildSetting;
    ChatManager manager { get { return ChatManager.Instance; } }
    protected override void InitComponent()
    {
        [SerializeField] Button m_CloseBtn;
        [SerializeField] Text m_ChatTip;
        [SerializeField] ChatSendComponent m_ChatSend;
        [SerializeField] ScrollerController m_ChannelControl;
        [SerializeField] ChatContentBehaviour m_ChatContent;
        [SerializeField] ChatRecently m_ChatRecently;
        [SerializeField] Button m_ChannelBtn;
        [SerializeField] Text m_ChannelInfo;
        protected override void InitComponent()
        base.InitComponent();
        btnClose.SetListener(CloseWindow);
        btnSendChat.SetListener(() =>
        {
            m_CloseBtn.onClick.AddListener(OnClose);
            m_ChannelBtn.onClick.AddListener(OnChannelBtn);
        }
        protected override void OnPreOpen()
        {
            if (!IsSatisfyShowChannel(ChatManager.Instance.presentChatType))
            // 如果在聊天输入界面无输入文字点击发送,则关闭聊天输入界面
            if (string.IsNullOrEmpty(inputChat.text))
            {
                ChatManager.Instance.presentChatType = ChatInfoType.System;
                CloseWindow();
                return;
            }
            // m_ChatSend.parent = this;
            ChatManager.Instance.lockUpdate = false;
            ChatManager.Instance.OnPteChatChangeEvent += OnPteChatChangeEvent;
            ChatManager.Instance.OpenPteChatEvent += OpenPteChatEvent;
            DisplayChannel();
            OnChatTypeChange();
            ChatCenter.Instance.UpdateChatContentPos();
        }
        protected override void OnOpen()
        {
            AchievementRandomWord();
            if (ChatManager.Instance.openFromDaily)
            if (!manager.CheckChatLimit(inputChat.text, out int errorCode))
            {
                AssitRandomChat();
                ChatManager.Instance.needCheckAssitChat = true;
                manager.ShowChatErrorTip(errorCode);
                return;
            }
            else if (ChatManager.Instance.openFromGem)
            manager.SendChatInfo(manager.nowChatChannel, inputChat.text);
            manager.AddChatChannelSendTime(manager.nowChatChannel, TimeUtility.AllSeconds);
            inputChat.text = string.Empty;
            UpdateSendButton();
        });
        btnNewMsgTip.SetListener(() =>
        {
            if (manager.nowChatChannel == ChatChannel.World)
            {
                string chat = Language.Get("ThanksGift" + UnityEngine.Random.Range(1, 4));
                if (chat != string.Empty)
                {
                    ChatCenter.Instance.ChangeChatValue(chat, false, true);
                }
                RefreshChat(manager.nowChatChannel, scrWorld);
                ScrollerJump(scrWorld, ChatChannel.World);
            }
            else if (ChatManager.Instance.openFromFairyTask)
            else if (manager.nowChatChannel == ChatChannel.Guild)
            {
                TaskRandomChat();
                RefreshChat(manager.nowChatChannel, scrGuild);
                ScrollerJump(scrGuild, ChatChannel.Guild);
            }
            ChatManager.Instance.openFromDaily = false;
            ChatManager.Instance.openFromGem = false;
            ChatManager.Instance.openFromFairyTask = false;
        }
        protected override void OnPreClose()
            ClearUnreadMsg();
        });
        btnSetting.SetListener(() =>
        {
            ChatManager.Instance.OnPteChatChangeEvent -= OnPteChatChangeEvent;
            ChatManager.Instance.OpenPteChatEvent -= OpenPteChatEvent;
            ChatManager.Instance.openFromDaily = false;
            ChatManager.Instance.openFromGem = false;
            ChatManager.Instance.needCheckAssitChat = false;
            ChatManager.Instance.openFromFairyTask = false;
            //ChatCenter.Instance.ChangeChatValue(string.Empty, false, true);
            //ChatManager.Instance.itemPlaceList.Clear();
        }
            isSettingOpen = !isSettingOpen;
            transSettings.SetActive(isSettingOpen);
        });
        protected override void OnClose()
        {
        }
    }
        private void OpenPteChatEvent()
        {
            OnChannelSelect(ChatInfoType.Friend);
        }
    // 清理未读消息状态
    private void ClearUnreadMsg()
    {
        unreadMsgCount = 0;
        btnNewMsgTip.SetActive(false);
    }
        private void DisplayChannel()
        {
            m_ChannelControl.Refresh();
            for (int i = 0; i < ChatCenter.Instance.chatChannels.Count; i++)
            {
                if (IsSatisfyShowChannel(ChatCenter.Instance.chatChannels[i]))
                {
                    m_ChannelControl.AddCell(ScrollerDataType.Normal, (int)ChatCenter.Instance.chatChannels[i], OnChannelSelect);
                }
            }
            m_ChannelControl.Restart();
    // 更新未读消息UI
    private void UpdateUnreadMsgUI()
    {
        btnNewMsgTip.SetActive(unreadMsgCount > 0);
        txtNewMsgTip.text = Language.Get("Chat10", unreadMsgCount);
    }
            m_ChannelControl.JumpIndex(Math.Min((int)ChatManager.Instance.presentChatType, m_ChannelControl.GetNumberOfCells(m_ChannelControl.m_Scorller) - 1));
    protected override void OnPreOpen()
    {
        base.OnPreOpen();
        manager.OnChatTabChangeEvent += OnChatTabChange;
        manager.OnUpdateTalkEvent += OnUpdateTalkEvent;
        manager.OnUpdateTalkCacheListEvent += OnUpdateTalkCacheList;
        }
        scrChatTab.OnRefreshCell += OnRefreshChatTabCell;
        scrWorld.OnGetDynamicSize += OnGetWorldChatDynamicSize;
        scrWorld.OnRefreshCell += OnRefreshWorldCell;
        scrWorld.mScrollRect.onValueChanged.AddListener(OnWorldScrollValChange);
        scrGuild.OnGetDynamicSize += OnGetWorldChatDynamicSize;
        scrGuild.OnRefreshCell += OnRefreshGuildCell;
        scrGuild.mScrollRect.onValueChanged.AddListener(OnGuildScrollValChange);
        private bool IsSatisfyShowChannel(ChatInfoType channel)
        {
        clickScreenOtherSpace.AddListener(OnClickScreenOtherSpace);
        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
            return true;
        }
        private void OnPteChatChangeEvent()
        {
            if (ChatManager.Instance.presentChatType == ChatInfoType.Friend)
            {
                OnChatTypeChange();
            }
        }
        private void OnChatTypeChange()
        {
            m_ChannelBtn.SetActive(false);
            m_ChannelInfo.SetActive(false);
            m_ChatSend.placeholder.text= Language.Get("L1111");
            m_CloseBtn.SetActive(ChatManager.Instance.presentChatType != ChatInfoType.Friend);
            switch (ChatManager.Instance.presentChatType)
            {
                case ChatInfoType.Trumpet:
                    m_ChatRecently.SetActive(false);
                    m_ChatTip.SetActive(false);
                    m_ChatSend.SetActive(true);
                    m_ChatSend.placeholder.text = Language.Get("L1012");
                    break;
                case ChatInfoType.Invite:
                case ChatInfoType.System:
                    m_ChatRecently.SetActive(false);
                    m_ChatTip.text = Language.Get("L1109");
                    m_ChatTip.SetActive(true);
                    m_ChatSend.SetActive(false);
                    break;
                case ChatInfoType.World:
                case ChatInfoType.Area:
                case ChatInfoType.CrossServer:
                case ChatInfoType.default1:
                    m_ChatRecently.SetActive(false);
                    m_ChatTip.SetActive(false);
                    m_ChatSend.SetActive(true);
                    break;
                case ChatInfoType.Team:
                    // TODO YYL
                    // m_ChatRecently.SetActive(false);
                    // var _team = ModelCenter.Instance.GetModel<TeamModel>().myTeam;
                    // m_ChatSend.SetActive(_team.teamId > 0);
                    // m_ChatTip.SetActive(_team.teamId <= 0);
                    // m_ChatTip.text = Language.Get("L1110");
                    break;
                case ChatInfoType.Fairy:
                    // TODO YYL
                    // m_ChatRecently.SetActive(false);
                    // m_ChannelBtn.SetActive(!PlayerDatas.Instance.fairyData.HasFairy);
                    // m_ChannelInfo.SetActive(!PlayerDatas.Instance.fairyData.HasFairy);
                    // m_ChatTip.SetActive(!PlayerDatas.Instance.fairyData.HasFairy);
                    // m_ChatSend.SetActive(PlayerDatas.Instance.fairyData.HasFairy);
                    // if (!PlayerDatas.Instance.fairyData.HasFairy)
                    // {
                    //     m_ChatTip.text = Language.Get("L1011");
                    // }
                    break;
                case ChatInfoType.Friend:
                    m_ChatSend.SetActive(true);
                    m_ChatTip.SetActive(false);
                    if (!m_ChatRecently.gameObject.activeSelf)
                    {
                        m_ChatRecently.SetActive(true);
                    }
                    break;
            }
            m_ChatContent.chatType = ChatManager.Instance.presentChatType;
            ChatManager.Instance.ViewChat(ChatManager.Instance.presentChatType);
        }
        private void OnChannelSelect(CellView _cell)
        {
            if ((ChatInfoType)_cell.index == ChatInfoType.CrossServer)
            {
                if (!FuncOpen.Instance.IsFuncOpen(162))
                {
                    SysNotifyMgr.Instance.ShowTip("CrossServerHint");
                    return;
                }
            }
            OnChannelSelect((ChatInfoType)_cell.index);
        }
        private void OnChannelSelect(ChatInfoType _type)
        {
            ChatManager.Instance.presentChatType = _type;
            m_ChannelControl.m_Scorller.RefreshActiveCellViews();
            if (_type == ChatInfoType.Friend)
            {
                ChatManager.Instance.lockUpdate = true;
            }
            else
            {
                ChatManager.Instance.lockUpdate = false;
            }
            OnChatTypeChange();
            ChatCenter.Instance.UpdateChatContentPos();
        }
        private void OnChannelBtn()
        {
            switch (ChatManager.Instance.presentChatType)
            {
                case ChatInfoType.Fairy:
                    {
                        int limit = FuncOpenLVConfig.Get((int)FuncOpenEnum.Guild).LimitLV;
                        if (PlayerDatas.Instance.baseData.LV < limit)
                        {
                            ServerTipDetails.DisplayNormalTip(Language.Get("L1136", limit));
                            return;
                        }
                        CloseWindow();
                        // TODO YYL
                        // WindowJumpMgr.Instance.WindowJumpTo(JumpUIType.UnionFunc3);
                    }
                    break;
            }
        }
        private void AchievementRandomWord()
        {
            // TODO YYL
            // if (AchievementGoto.achievementType != AchievementGoto.RandomFairyChat
            //     && AchievementGoto.achievementType != AchievementGoto.RandomWorldChat)
            // {
            //     return;
            // }
            // AchievementGoto.achievementType = 0;
            // if (AchievementGoto.achievementType == AchievementGoto.RandomFairyChat && !PlayerDatas.Instance.fairyData.HasFairy)
            // {
            //     return;
            // }
            // if (ChatManager.Instance.achievementRandoms.ContainsKey(ChatManager.Instance.presentChatType))
            // {
            //     var _list = ChatManager.Instance.achievementRandoms[ChatManager.Instance.presentChatType];
            //     int _index = UnityEngine.Random.Range(0, _list.Count);
            //     ChatCenter.Instance.ChangeChatValue(Language.Get(_list[_index]), false, true);
            // }
            // var _effect = AchievementGuideEffectPool.Require(1);
            // _effect.transform.SetParentEx(m_ChatSend.sendBtn.transform, Vector3.zero, Vector3.zero, Vector3.one);
        }
        private void AssitRandomChat()
        {
            ChatCenter.Instance.ChangeChatValue(ChatManager.Instance.GetAssitRandomChat(ChatManager.Instance.presentChatType), false, true);
        }
        private void TaskRandomChat()
        {
            ChatCenter.Instance.ChangeChatValue(ChatManager.Instance.GetTaskRandomChat(ChatManager.Instance.presentChatType), false, true);
        }
        private void GemFlauntChat()
        {
            // TODO YYL
            // ChatCenter.Instance.ChangeChatValue(ChatManager.Instance.GetGemFlauntChat(), false, true);
            // var _effect = AchievementGuideEffectPool.Require(1);
            // _effect.transform.SetParentEx(m_ChatSend.sendBtn.transform, Vector3.zero, Vector3.zero, Vector3.one);
        }
        isSettingOpen = false;
        transSettings.SetActive(isSettingOpen);
        btnWorldSetting.SetChannelType(ChatChannel.World);
        btnGuildSetting.SetChannelType(ChatChannel.Guild);
        inputChat.characterLimit = ChatManager.Instance.characterLimit;
        CreaterAll(manager.nowChatTab);
    }
    protected override void OnPreClose()
    {
        base.OnPreClose();
        manager.OnChatTabChangeEvent -= OnChatTabChange;
        manager.OnUpdateTalkEvent -= OnUpdateTalkEvent;
        manager.OnUpdateTalkCacheListEvent -= OnUpdateTalkCacheList;
        scrChatTab.OnRefreshCell -= OnRefreshChatTabCell;
        scrWorld.OnGetDynamicSize -= OnGetWorldChatDynamicSize;
        scrWorld.OnRefreshCell -= OnRefreshWorldCell;
        scrWorld.mScrollRect.onValueChanged.RemoveListener(OnWorldScrollValChange);
        scrGuild.OnGetDynamicSize -= OnGetGuildChatDynamicSize;
        scrGuild.OnRefreshCell -= OnRefreshGuildCell;
        scrGuild.mScrollRect.onValueChanged.RemoveListener(OnGuildScrollValChange);
        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
        clickScreenOtherSpace.RemoveAllListeners();
    }
    private void OnRefreshGuildCell(ScrollerDataType type, CellView cell)
    {
        OnRefreshCell(type, cell);
    }
    private void OnRefreshWorldCell(ScrollerDataType type, CellView cell)
    {
        OnRefreshCell(type, cell);
    }
    private void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        if (type == ScrollerDataType.Header)
        {
            var _cell = cell.GetComponent<ChatPlayerMineCell>();
            _cell?.Refresh(cell);
        }
        else if (type == ScrollerDataType.Normal)
        {
            var _cell = cell.GetComponent<ChatPlayerOtherCell>();
            _cell?.Refresh(cell);
        }
        else if (type == ScrollerDataType.Tail)
        {
            var _cell = cell.GetComponent<ChatSysCell>();
            _cell?.Refresh(cell);
        }
        else if (type == ScrollerDataType.Extra1)
        {
            var _cell = cell.GetComponent<ChatDateCell>();
            _cell?.Refresh(cell);
        }
    }
    private void OnSecondEvent()
    {
        UpdateSendButton();
    }
    private void OnClickScreenOtherSpace()
    {
        isSettingOpen = !isSettingOpen;
        transSettings.SetActive(isSettingOpen);
    }
    private bool m_isJumpArea;
    public bool isJumpArea
    {
        get { return m_isJumpArea; }
        set
        {
            if (m_isJumpArea == value)
                return;
            m_isJumpArea = value;
            // isJumpArea = true (用户在底部):开启锁定底部
            if (value)
            {
                if (scrWorld.lockType != EnhanceLockType.LockVerticalBottom)
                    scrWorld.lockType = EnhanceLockType.LockVerticalBottom;
                // 如果回到底部,直接清零消息
                ClearUnreadMsg();
            }
            // isJumpArea = false (用户看历史):保持视觉位置
            else
            {
                if (scrWorld.lockType != EnhanceLockType.KeepVertical)
                    scrWorld.lockType = EnhanceLockType.KeepVertical;
            }
        }
    }
    private void OnWorldScrollValChange(Vector2 _pos)
    {
        OnScrollValChange(scrWorld, _pos);
    }
    private void OnGuildScrollValChange(Vector2 _pos)
    {
        OnScrollValChange(scrGuild, _pos);
    }
    private void OnScrollValChange(ScrollerController scorller, Vector2 _pos)
    {
        if (scorller.m_Scorller._ScrollSize <= 0)
            return;
        float _value = m_Percent / scorller.m_Scorller._ScrollSize * scorller.m_Scorller.ScrollRectSize;
        isJumpArea = _pos.y <= _value;
        // 检查滚动位置是否覆盖了新消息
        if (unreadMsgCount <= 0)
            return;
        int totalCount = scorller.GetNumberOfCells(scorller.m_Scorller);
        int thresholdIndex = totalCount - unreadMsgCount;
        // 获取当前视窗最底部显示的 Item 索引
        int currentBottomIndex = scorller.m_Scorller.EndDataIndex;
        // 如果当前看到的底部索引 超过了 新消息的起始线(减1是为了容错)
        if (currentBottomIndex >= thresholdIndex - 1)
        {
            ClearUnreadMsg();
        }
    }
    private void OnChatTabChange(ChatTab entrance)
    {
        CreaterAll(entrance);
    }
    private void OnUpdateTalkEvent(ChatChannel type, TalkData data)
    {
        RefreshAll(type, playerId: data.PlayerID);
    }
    private void OnUpdateTalkCacheList()
    {
        RefreshAll(manager.nowChatChannel);
    }
    private void CreaterAll(ChatTab chatTab)
    {
        if (chatTab == ChatTab.World)
        {
            manager.nowChatChannel = ChatChannel.World;
        }
        else if (chatTab == ChatTab.Guild)
        {
            manager.nowChatChannel = ChatChannel.Guild;
        }
        UpdateSendButton();
        // 打开界面时默认到底部,无未读
        isJumpArea = true;
        scrWorld.lockType = EnhanceLockType.LockVerticalBottom; // 初始锁定底部
        scrWorld.SetActive(chatTab == ChatTab.World);
        scrGuild.lockType = EnhanceLockType.LockVerticalBottom; // 初始锁定底部
        scrGuild.SetActive(chatTab == ChatTab.Guild);
        transInput.SetActive(chatTab == ChatTab.World || chatTab == ChatTab.Guild);
        CreateChatTabScroller();
        switch (chatTab)
        {
            case ChatTab.World:
                manager.nowChatChannel = ChatChannel.World;
                CreateScroller(scrWorld, ChatChannel.World);
                ScrollerJump(scrWorld, ChatChannel.World);
                ClearUnreadMsg();
                break;
            case ChatTab.Guild:
                manager.nowChatChannel = ChatChannel.Guild;
                CreateScroller(scrGuild, ChatChannel.Guild);
                ScrollerJump(scrGuild, ChatChannel.Guild);
                ClearUnreadMsg();
                break;
        }
    }
    float KeepArea(ScrollerController scroller)
    {
        if (scroller.GetNumberOfCells(scroller.m_Scorller) >= manager.maxTalkCount)
        {
            float totalRemovedSize = 0f;
            for (int i = 0; i < manager.deleteTalkCount; i++)
            {
                float cellSize = scroller.GetCellSize(i);
                totalRemovedSize += cellSize + scroller.m_Scorller.spacing;
            }
            return totalRemovedSize;
        }
        return 0;
    }
    private void RefreshAll(ChatChannel type, uint playerId = 0)
    {
        scrChatTab.m_Scorller.RefreshActiveCellViews();
        if (type == ChatChannel.World)
        {
            RefreshChat(type, scrWorld, playerId);
        }
        else if (type == ChatChannel.Guild)
        {
            RefreshChat(type, scrGuild, playerId);
        }
    }
    private void RefreshChat(ChatChannel type, ScrollerController scroller, uint playerId = 0)
    {
        if (!manager.TryGetTalkData(type, out List<TalkData> datas) || datas == null)
            return;
        int numberOfCells = scroller.GetNumberOfCells(scroller.m_Scorller);
        if (numberOfCells < manager.maxTalkCount)
        {
            for (int i = numberOfCells; i < datas.Count; i++)
            {
                TalkData data = datas[i];
                ScrollerDataType scrollerDataType = GetCellType(data);
                scroller.AddCell(scrollerDataType, i);
                int talkDataType = manager.GetTalkDataType(data);
                float height = GetHeight(talkDataType, data.Content, data.InfoList);
                scroller.m_Scorller.AddHeight(true, height);
                //Debug.Log($"ChatWin AddCell i {i} AddHeight {height}");
            }
        }
        else
        {
            scroller.m_Scorller.RefreshActiveCellViews();
        }
        if (type == ChatChannel.World && manager.nowChatTab != ChatTab.World)
            return;
        if (type == ChatChannel.Guild && manager.nowChatTab != ChatTab.Guild)
            return;
        // 1. 自己发送的消息 -> 强制跳转到底部 + 清零
        if (playerId == PlayerDatas.Instance.PlayerId)
        {
            isJumpArea = true;
            scroller.lockType = EnhanceLockType.LockVerticalBottom;
            ScrollerJump(scroller, type);
            ClearUnreadMsg(); // 自己发的消息不用提示
        }
        // 2. 别人发消息 & 当前在底部 -> 自动跟随 + 清零
        else if (isJumpArea)
        {
            scroller.lockType = EnhanceLockType.LockVerticalBottom;
            ScrollerJump(scroller, type);
            ClearUnreadMsg(); // 在底部看着不用提示
        }
        // 3. 别人发消息 & 当前在看历史 -> 保持位置 + 增加未读计数
        else
        {
            scroller.lockType = EnhanceLockType.KeepVertical;
            float offset = KeepArea(scroller);
            if (Math.Abs(offset) > 0.001f)
            {
                ScrollerJump(scroller, offset);
            }
            if (type == manager.nowChatChannel)
            {
                unreadMsgCount++;
                UpdateUnreadMsgUI();
            }
            // 特殊情况:如果未读数量巨大(超过了总显示数量),说明整个列表都被刷新了,直接消零
            if (unreadMsgCount >= scrWorld.GetNumberOfCells(scrWorld.m_Scorller))
            {
                ClearUnreadMsg();
            }
        }
    }
    private bool OnGetWorldChatDynamicSize(ScrollerDataType _type, int _index, out float height)
    {
        return OnGetChatDynamicSize(_type, _index, out height);
    }
    private bool OnGetGuildChatDynamicSize(ScrollerDataType _type, int _index, out float height)
    {
        return OnGetChatDynamicSize(_type, _index, out height);
    }
    private bool OnGetChatDynamicSize(ScrollerDataType _type, int _index, out float height)
    {
        height = 0;
        if (!manager.TryGetChatData(manager.nowChatChannel, _index, out TalkData data) || data == null)
            return false;
        switch (_type)
        {
            case ScrollerDataType.Header:
                height = m_ChatMineCell.GetHeight(data.Content, data.InfoList);
                return true;
            case ScrollerDataType.Normal:
                height = m_ChatOtherCell.GetHeight(data.Content, data.InfoList);
                return true;
            case ScrollerDataType.Tail:
                height = m_ChatSysCell.GetHeight(data.Content, data.InfoList);
                return true;
            case ScrollerDataType.Extra1:
                height = 30;
                return true;
        }
        return true;
    }
    private void OnRefreshChatTabCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell.GetComponent<ChatTabCell>();
        _cell?.Display(cell.index, cell);
    }
    private void CreateChatTabScroller()
    {
        scrChatTab.Refresh();
        for (int i = 0; i < manager.tabShowList.Count; i++)
        {
            CellInfo cellInfo = new CellInfo();
            cellInfo.infoInt1 = (int)manager.tabShowList[i];
            scrChatTab.AddCell(ScrollerDataType.Header, i, cellInfo);
        }
        scrChatTab.Restart();
    }
    private void CreateScroller(ScrollerController scroller, ChatChannel type)
    {
        scroller.Refresh();
        if (manager.TryGetTalkData(type, out List<TalkData> datas))
        {
            for (int i = 0; i < datas.Count; i++)
            {
                TalkData data = datas[i];
                ScrollerDataType scrollerDataType = GetCellType(data);
                scroller.AddCell(scrollerDataType, i);
            }
        }
        scroller.Restart();
    }
    private void ScrollerJump(ScrollerController scroller, ChatChannel type)
    {
        scroller.lockType = EnhanceLockType.LockVerticalBottom;
        scroller.ResetScrollPos();
        int jumpIndex = manager.GetJumpIndex(type);
        scroller.JumpIndex(jumpIndex);
        //Debug.Log($"ChatWin JumpIndex {jumpIndex}");
        isJumpArea = true;
    }
    private void ScrollerJump(ScrollerController scroller, float _offset)
    {
        scroller.JumpIndex(-_offset, 0, EnhancedUI.EnhancedScroller.EnhancedScroller.TweenType.immediate);
    }
    // 0-系统 1-日期 2-自己 3-其他玩家
    private ScrollerDataType GetCellType(TalkData data)
    {
        int type = manager.GetTalkDataType(data);
        if (type == 0)
            return ScrollerDataType.Tail;
        else if (type == 1)
            return ScrollerDataType.Extra1;
        else if (type == 2)
            return ScrollerDataType.Header;
        else
            return ScrollerDataType.Normal;
    }
    public float GetHeight(int type, string content, ArrayList list)
    {
        switch (type)
        {
            case 0:
                return m_ChatSysCell.GetHeight(content, list);
            case 1:
                return 30;
            case 2:
                return m_ChatMineCell.GetHeight(content, list);
            case 3:
                return m_ChatOtherCell.GetHeight(content, list);
        }
        return 0;
    }
    private void UpdateSendButton()
    {
        bool isCanSend = manager.IsCanSend(manager.nowChatChannel, out int remainingSeconds);
        btnSendChat.interactable = isCanSend;
        imgSendChat.gray = !isCanSend;
        txtSendChat.text = isCanSend ? Language.Get("Chat02") : Language.Get("Chat14", remainingSeconds);
        txtSendChat.colorType = isCanSend ? TextColType.NavyBrown : TextColType.LightWhite;
    }
}