local A, L = ... local options = L.C -------------------------------------- -- grab from elvui chat module local _G = _G local gsub, strfind, gmatch, format, max = gsub, strfind, gmatch, format, max local ipairs, sort, wipe, time, difftime = ipairs, sort, wipe, time, difftime local pairs, unpack, select, tostring, pcall, next, tonumber, type = pairs, unpack, select, tostring, pcall, next, tonumber, type local strlower, strsub, strlen, strupper, strtrim, strmatch = strlower, strsub, strlen, strupper, strtrim, strmatch local tinsert, tremove, tconcat = tinsert, tremove, table.concat local Ambiguate = Ambiguate local BetterDate = BetterDate local BNGetFriendInfo = BNGetFriendInfo local BNGetFriendInfoByID = BNGetFriendInfoByID local BNGetNumFriendInvites = BNGetNumFriendInvites local BNGetNumFriends = BNGetNumFriends local CreateFrame = CreateFrame local FlashClientIcon = FlashClientIcon local GetBNPlayerCommunityLink = GetBNPlayerCommunityLink local GetBNPlayerLink = GetBNPlayerLink local GetChannelName = GetChannelName local GetChatWindowInfo = GetChatWindowInfo local GetCursorPosition = GetCursorPosition local GetCVar, GetCVarBool = GetCVar, GetCVarBool local GetGuildRosterMOTD = GetGuildRosterMOTD local GetInstanceInfo = GetInstanceInfo local GetMouseFocus = GetMouseFocus local GetNumGroupMembers = GetNumGroupMembers local GetPlayerCommunityLink = GetPlayerCommunityLink local GetPlayerInfoByGUID = GetPlayerInfoByGUID local GetPlayerLink = GetPlayerLink local GetRaidRosterInfo = GetRaidRosterInfo local GMChatFrame_IsGM = GMChatFrame_IsGM local GMError = GMError local hooksecurefunc = hooksecurefunc local InCombatLockdown = InCombatLockdown local IsAltKeyDown = IsAltKeyDown local IsInRaid, IsInGroup = IsInRaid, IsInGroup local IsShiftKeyDown = IsShiftKeyDown local PlaySoundFile = PlaySoundFile local RemoveExtraSpaces = RemoveExtraSpaces local RemoveNewlines = RemoveNewlines local ToggleFrame = ToggleFrame local UnitName = UnitName local C_DateAndTime_GetCurrentCalendarTime = C_DateAndTime.GetCurrentCalendarTime local C_Club_GetInfoFromLastCommunityChatLine = C_Club.GetInfoFromLastCommunityChatLine local Chat_GetChatCategory = Chat_GetChatCategory local ChatHistory_GetAccessID = ChatHistory_GetAccessID local ChatFrame_ResolvePrefixedChannelName = ChatFrame_ResolvePrefixedChannelName local BNet_GetValidatedCharacterName = BNet_GetValidatedCharacterName local BNet_GetClientEmbeddedTexture = BNet_GetClientEmbeddedTexture local BNET_CLIENT_WOW = BNET_CLIENT_WOW local tabTexs = { '', 'Selected', 'Highlight' } local function GetDockerParent(docker, chat) if not docker then return end local _, relativeTo = chat:GetPoint() if relativeTo == docker then return docker:GetParent() end end local function UpdateEditboxAnchors(self) local cvar = (type(self) == 'string' and self) or GetCVar('chatStyle') local classic = cvar == 'classic' local leftChat = classic and _G.LeftChatPanel local panel = 22 for _, name in ipairs(_G.CHAT_FRAMES) do local frame = _G[name] local editbox = frame and frame.editBox if not editbox then return end editbox.chatStyle = cvar editbox:ClearAllPoints() local anchorTo = leftChat or frame local below, belowInside = options.editBoxPosition == 'BELOW_CHAT', options.editBoxPosition == 'BELOW_CHAT_INSIDE' if below or belowInside then -- local showLeftPanel = E.db.datatexts.panels.LeftChatDataPanel.enable editbox:SetPoint('TOPLEFT', anchorTo, 'BOTTOMLEFT', classic and 0 or -2, (classic and (belowInside and 1 or 0) or -5)) editbox:SetPoint('BOTTOMRIGHT', anchorTo, 'BOTTOMRIGHT', classic and 0 or -2, (classic and (belowInside and 1 or 0) or -5) + (belowInside and panel or -panel)) else local aboveInside = options.editBoxPosition == 'ABOVE_CHAT_INSIDE' editbox:SetPoint('BOTTOMLEFT', anchorTo, 'TOPLEFT', classic and (aboveInside and 1 or 0) or -2, (classic and (aboveInside and -1 or 0) or 2)) editbox:SetPoint('TOPRIGHT', anchorTo, 'TOPRIGHT', classic and (aboveInside and -1 or 0) or 2, (classic and (aboveInside and -1 or 0) or 2) + (aboveInside and -panel or panel)) end end end local function RepositionOverflowButton() _G.GeneralDockManagerOverflowButton:ClearAllPoints() _G.GeneralDockManagerOverflowButton:SetPoint('RIGHT', _G.ChatFrameChannelButton, 'LEFT', -4, 0) end local function CreateChatVoicePanel() local Holder = CreateFrame('Frame', 'ChatButtonHolder', UIParent) Holder:ClearAllPoints() Holder:SetPoint('BOTTOMLEFT', _G.LeftChatPanel, 'TOPLEFT', 0, 1) Holder:SetSize(30, 86) Holder.backdrop = L.CreateBackdrop(Holder) Holder.backdrop:SetBackdropColor(options.panelColor.r, options.panelColor.g, options.panelColor.b, options.panelColor.a) --create drag frame rLib:CreateDragFrame(Holder, L.dragFrames, -2, true) _G.ChatFrameChannelButton:ClearAllPoints() _G.ChatFrameChannelButton:SetPoint('TOP', Holder, 'TOP', 0, -2) _G.ChatFrameChannelButton.Icon:SetParent(_G.ChatFrameChannelButton) _G.ChatFrameChannelButton.Icon:SetDesaturated(options.desaturateVoiceIcons) _G.ChatFrameChannelButton:SetParent(Holder) _G.ChatAlertFrame:ClearAllPoints() _G.ChatAlertFrame:SetPoint('BOTTOM', _G.ChatFrameChannelButton, 'TOP', 1, 3) end local function HandleChatVoiceIcons() if options.hideVoiceButtons then _G.ChatFrameChannelButton:Hide() elseif options.pinVoiceButtons then _G.ChatFrameChannelButton.Icon:SetDesaturated(options.desaturateVoiceIcons) _G.ChatFrameChannelButton:ClearAllPoints() _G.ChatFrameChannelButton:SetPoint('RIGHT', _G.GeneralDockManager, 'RIGHT', 2, 0) RepositionOverflowButton() else CreateChatVoicePanel() end if not options.hideVoiceButtons then _G.GeneralDockManagerOverflowButtonList:SetFrameStrata('LOW') _G.GeneralDockManagerOverflowButtonList:SetFrameLevel(5) end if not options.pinVoiceButtons then _G.GeneralDockManagerOverflowButton:ClearAllPoints() _G.GeneralDockManagerOverflowButton:SetPoint('RIGHT', _G.GeneralDockManager, 'RIGHT', -4, 0) end end local function UpdateFading() for _, frameName in ipairs(_G.CHAT_FRAMES) do local frame = _G[frameName] if frame then frame:SetTimeVisible(options.inactivityTimer) frame:SetFading(options.fade) end end end local canChangeMessage = function(arg1, id) if id and arg1 == '' then return id end end local function MessageIsProtected(message) return message and (message ~= gsub(message, '(:?|?)|K(.-)|k', canChangeMessage)) end local function GetOwner(tab) if not tab.owner then tab.owner = _G[format('ChatFrame%s', tab:GetID())] end return tab.owner end local function GetTab(chat) if not chat.tab then chat.tab = _G[format('ChatFrame%sTab', chat:GetID())] end return chat.tab end local function ChatFrameTab_SetAlpha(self, _, skip) if skip then return end local chat = GetOwner(self) self:SetAlpha((not chat.isDocked or self.selected) and 1 or 0.6, true) end local function ShowBackground(background, show) if not background then return end if show then background.Show = nil background:Show() else L.Kill(background) end end local function TabOnEnter(tab) tab.Text:Show() if tab.conversationIcon then tab.conversationIcon:Show() end if not options.hideCopyButton then local chat = GetOwner(tab) if chat and chat.copyButton and GetMouseFocus() ~= chat.copyButton then chat.copyButton:SetAlpha(0.35) end end end local function TabOnLeave(tab) tab.Text:Hide() if tab.conversationIcon then tab.conversationIcon:Hide() end if not options.hideCopyButton then local chat = GetOwner(tab) if chat and chat.copyButton and GetMouseFocus() ~= chat.copyButton then chat.copyButton:SetAlpha(0) end end end local function ChatOnEnter(chat) TabOnEnter(GetTab(chat)) end local function ChatOnLeave(chat) TabOnLeave(GetTab(chat)) end local function IsUndocked(chat, docker) if not docker then docker = _G.GeneralDockManager.primary end local primaryUndocked = docker ~= rChatPlus.LeftChatWindow and docker ~= rChatPlus.RightChatWindow return not chat.isDocked or (primaryUndocked and ((chat == docker) or GetDockerParent(docker, chat))) end local function HandleFadeTabs(chat, hook) local tab = GetTab(chat) if hook then chat:SetScript('OnEnter', ChatOnEnter) chat:SetScript('OnLeave', ChatOnLeave) tab:SetScript('OnEnter', TabOnEnter) tab:SetScript('OnLeave', TabOnLeave) else chat:SetScript('OnEnter', nil) chat:SetScript('OnLeave', nil) tab:SetScript('OnEnter', nil) tab:SetScript('OnLeave', nil) end local focus = GetMouseFocus() if not hook then TabOnEnter(tab) elseif focus ~= tab and focus ~= chat then TabOnLeave(tab) end end local function UpdateChatTab(chat) local fadeLeft, fadeRight if options.fadeTabsNoBackdrop then local both = options.panelBackdrop == 'HIDEBOTH' fadeLeft = (both or options.panelBackdrop == 'RIGHT') fadeRight = (both or options.panelBackdrop == 'LEFT') end if chat == rChatPlus.LeftChatWindow then GetTab(chat):SetParent(_G.LeftChatPanel or _G.UIParent) chat:SetParent(_G.LeftChatPanel or _G.UIParent) HandleFadeTabs(chat, fadeLeft) elseif chat == rChatPlus.RightChatWindow then GetTab(chat):SetParent(_G.RightChatPanel or _G.UIParent) chat:SetParent(_G.RightChatPanel or _G.UIParent) HandleFadeTabs(chat, fadeRight) else local docker = _G.GeneralDockManager.primary local parent = GetDockerParent(docker, chat) -- we need to update the tab parent to mimic the docker GetTab(chat):SetParent(parent or _G.UIParent) chat:SetParent(parent or _G.UIParent) if parent and docker == rChatPlus.LeftChatWindow then HandleFadeTabs(chat, fadeLeft) elseif parent and docker == rChatPlus.RightChatWindow then HandleFadeTabs(chat, fadeRight) else HandleFadeTabs(chat, options.fadeUndockedTabs and IsUndocked(chat, docker)) end end end local function UpdateChatTabs() for _, name in ipairs(_G.CHAT_FRAMES) do UpdateChatTab(_G[name]) end end local function GetAnchorParents(chat) local Left = (chat == rChatPlus.LeftChatWindow and _G.LeftChatPanel) local Right = (chat == rChatPlus.RightChatWindow and _G.RightChatPanel) local Chat, TabPanel = Left or Right or _G.UIParent return TabPanel or Chat, Chat end local function ReparentVoiceChatIcon(parent) if not parent then parent = GetAnchorParents(_G.GeneralDockManager.primary) end _G.ChatFrameChannelButton:SetParent(parent) end local function FindChatWindows() if not options.panelSnapping then return end local left, right = rChatPlus.LeftChatWindow, rChatPlus.RightChatWindow -- they already exist just return them :) if left and right then return left, right end local docker = _G.GeneralDockManager.primary for _, name in ipairs(_G.CHAT_FRAMES) do local chat = _G[name] if (chat.isDocked and docker) or chat:IsShown() then if not left and L.FramesOverlap(chat, _G.LeftChatPanel) then left = chat elseif not right and L.FramesOverlap(chat, _G.RightChatPanel) then right = chat end -- if both are found just return now, don't wait if left and right then return left, right end end end -- none or one was found return left, right end local function PositionChat(chat) rChatPlus.LeftChatWindow, rChatPlus.RightChatWindow = FindChatWindows() local docker = _G.GeneralDockManager.primary if chat == docker then local iconParent, chatParent = GetAnchorParents(chat) _G.GeneralDockManager:SetParent(chatParent) if options.pinVoiceButtons and not options.hideVoiceButtons then ReparentVoiceChatIcon(iconParent or chatParent) end end UpdateChatTab(chat) if chat:IsMovable() then chat:SetUserPlaced(true) end if chat.FontStringContainer then chat.FontStringContainer:ClearAllPoints() chat.FontStringContainer:SetPoint('TOPLEFT', chat, 'TOPLEFT', -1, 1) chat.FontStringContainer:SetPoint('BOTTOMRIGHT', chat, 'BOTTOMRIGHT', 1, -1) end if chat:IsShown() then -- that chat font container leaks outside of its frame -- we cant clip it, so lets force that leak sooner so -- i can position it properly, patch: 8.3.0 ~Simpy chat:Hide() chat:Show() end local BASE_OFFSET = 32 if chat == rChatPlus.LeftChatWindow then local LOG_OFFSET = chat:GetID() == 2 and (_G.LeftChatTab:GetHeight() + 4) or 0 chat:ClearAllPoints() chat:SetPoint('BOTTOMLEFT', _G.LeftChatPanel, 'BOTTOMLEFT', 5, 5) chat:SetSize(options.panelWidth - 10, options.panelHeight - BASE_OFFSET - LOG_OFFSET) ShowBackground(chat.Background, false) elseif chat == rChatPlus.RightChatWindow then local LOG_OFFSET = chat:GetID() == 2 and (_G.LeftChatTab:GetHeight() + 4) or 0 chat:ClearAllPoints() chat:SetPoint('BOTTOMLEFT', _G.RightChatPanel, 'BOTTOMLEFT', 5, 5) chat:SetSize((options.separateSizes and options.panelWidthRight or options.panelWidth) - 10, (options.separateSizes and options.panelHeightRight or options.panelHeight) - BASE_OFFSET - LOG_OFFSET) ShowBackground(chat.Background, false) else -- show if: not docked, or ChatFrame1, or attached to ChatFrame1 ShowBackground(chat.Background, IsUndocked(chat, docker)) end end local function PositionChats() for _, name in ipairs(_G.CHAT_FRAMES) do PositionChat(_G[name]) end end local copyLines = {} function GetLines(frame) local index = 1 for i = 1, frame:GetNumMessages() do local message, r, g, b = frame:GetMessageInfo(i) if message and not MessageIsProtected(message) then --Set fallback color values r, g, b = r or 1, g or 1, b or 1 copyLines[index] = message index = index + 1 end end return index - 1 end local function CopyChat(frame) if not _G.CopyChatFrame:IsShown() then local _, fontSize = _G.FCF_GetChatWindowInfo(frame:GetID()) if fontSize < 10 then fontSize = 12 end _G.FCF_SetChatWindowFontSize(frame, frame, 0.01) _G.CopyChatFrame:Show() local lineCt = GetLines(frame) local text = tconcat(copyLines, ' \n', 1, lineCt) _G.FCF_SetChatWindowFontSize(frame, frame, fontSize) _G.CopyChatFrameEditBox:SetText(text) else _G.CopyChatFrame:Hide() end end local function CopyButtonOnMouseUp(self, btn) local chat = self:GetParent() if btn == 'RightButton' and chat:GetID() == 1 then ToggleFrame(_G.ChatMenu) else CopyChat(chat) end end local function CopyButtonOnEnter(self) self:SetAlpha(1) end local function CopyButtonOnLeave(self) local chat = self:GetParent() if _G[chat:GetName()..'TabText']:IsShown() then self:SetAlpha(0.35) else self:SetAlpha(0) end end local function ToggleChatButton(button) if button then button:SetShown(not options.hideCopyButton) end end local function Panels_ColorUpdate() local panelColor = options.panelColor _G.LeftChatPanel.backdrop:SetBackdropColor(panelColor.r, panelColor.g, panelColor.b, panelColor.a) if _G.ChatButtonHolder then _G.ChatButtonHolder:SetBackdropColor(panelColor.r, panelColor.g, panelColor.b, panelColor.a) end end local function StyleChat(frame) local name = frame:GetName() local tab = GetTab(frame) frame:SetTimeVisible(options.inactivityTimer) frame:SetMaxLines(options.maxLines) frame:SetFading(options.fade) if frame.styled then return end frame:SetFrameLevel(4) frame:SetClampRectInsets(0,0,0,0) frame:SetClampedToScreen(false) L.StripTextures(frame, true) L.Kill(_G[name..'ButtonFrame']) local editbox = frame.editBox for _, texName in pairs(tabTexs) do _G[name..'Tab'..texName..'Left']:SetTexture() _G[name..'Tab'..texName..'Middle']:SetTexture() _G[name..'Tab'..texName..'Right']:SetTexture() end hooksecurefunc(tab, 'SetAlpha', ChatFrameTab_SetAlpha) if not tab.left then tab.left = _G[name..'TabLeft'] end tab.Text:ClearAllPoints() tab.Text:SetPoint('LEFT', tab, 'LEFT', tab.left:GetWidth(), 0) tab:SetHeight(22) if tab.conversationIcon then tab.conversationIcon:ClearAllPoints() tab.conversationIcon:SetPoint('RIGHT', tab.Text, 'LEFT', -1, 0) end --local a, b, c = select(6, editbox:GetRegions()); a:Kill(); b:Kill(); c:Kill() L.Kill(_G[name..'EditBoxLeft']) L.Kill(_G[name..'EditBoxMid']) L.Kill(_G[name..'EditBoxRight']) editbox:SetAltArrowKeyMode(options.useAltKey) --copy chat button local copyButton = CreateFrame('Frame', format('%sCopyChatButton%d', A, id), frame) copyButton:EnableMouse(true) copyButton:SetAlpha(0.35) copyButton:SetSize(20, 22) copyButton:SetPoint('TOPRIGHT', 0, -4) copyButton:SetFrameLevel(frame:GetFrameLevel() + 5) frame.copyButton = copyButton local copyTexture = L.CreateIcon(frame.copyButton, 'OVERLAY') copyTexture:SetTexture(options.mediapath .. "Copy.tga") copyButton.texture = copyTexture copyButton:SetScript('OnMouseUp', CopyButtonOnMouseUp) copyButton:SetScript('OnEnter', CopyButtonOnEnter) copyButton:SetScript('OnLeave', CopyButtonOnLeave) ToggleChatButton(copyButton) frame.styled = true end local function SetupChat() for _, frameName in ipairs(_G.CHAT_FRAMES) do local frame = _G[frameName] local id = frame:GetID() StyleChat(frame) _G.FCFTab_UpdateAlpha(frame) end local chat = _G.GeneralDockManager.primary _G.GeneralDockManager:ClearAllPoints() _G.GeneralDockManager:SetPoint('BOTTOMLEFT', chat, 'TOPLEFT', 0, 3) _G.GeneralDockManager:SetPoint('BOTTOMRIGHT', chat, 'TOPRIGHT', 0, 3) _G.GeneralDockManager:SetHeight(22) _G.GeneralDockManagerScrollFrame:SetHeight(22) _G.GeneralDockManagerScrollFrameChild:SetHeight(22) PositionChats() if not rChatPlus.HookSecured then hooksecurefunc("FCF_OpenTemporaryWindow", SetupChat) rChatPlus.HookSecured = true end end local function UpdateEditboxFont(chatFrame) local style = GetCVar('chatStyle') if style == 'classic' and rChatPlus.LeftChatWindow then chatFrame = rChatPlus.LeftChatWindow end if chatFrame == _G.GeneralDockManager.primary then chatFrame = _G.GeneralDockManager.selected end local editbox = _G.ChatEdit_ChooseBoxForSend(chatFrame) -- the header and text will not update the placement without focus if editbox and editbox:IsShown() then editbox:SetFocus() end end local function ChatEdit_SetLastActiveWindow(editbox) local style = editbox.chatStyle or GetCVar('chatStyle') if style == 'im' then editbox:SetAlpha(0.5) end end local function ChatEdit_DeactivateChat(editbox) local style = editbox.chatStyle or GetCVar('chatStyle') if style == 'im' then editbox:Hide() end end local function ChatEdit_ActivateChat(editbox) if editbox and editbox.chatFrame then UpdateEditboxFont(editbox.chatFrame) end end local function ChatEdit_OnEnterPressed(editBox) -- editBox:ClearHistory() -- we will use our own editbox history so keeping them populated on blizzards end is pointless local chatType = editBox:GetAttribute('chatType') local chatFrame = chatType and editBox:GetParent() if chatFrame and (not chatFrame.isTemporary) and (_G.ChatTypeInfo[chatType].sticky == 1) then if not options.sticky then chatType = 'SAY' end editBox:SetAttribute('chatType', chatType) end end local function GetCombatLog() local LOG = _G.ChatFrame2 -- ChatFrame2 if LOG then return LOG, GetTab(LOG) end end local function FCFDock_UpdateTabs(dock) if dock == _G.GeneralDockManager then local logchat, logchattab = GetCombatLog() dock.scrollFrame:ClearAllPoints() dock.scrollFrame:SetPoint('RIGHT', dock.overflowButton, 'LEFT') dock.scrollFrame:SetPoint('TOPLEFT', (logchat.isDocked and logchattab) or GetTab(dock.primary), 'TOPRIGHT') end end local function FCF_Close(chat) -- clear these off when it's closed, used by FCFTab_UpdateColors local tab = GetTab(chat) tab.whisperName = nil tab.classColor = nil end local function FCF_SetWindowAlpha(frame, alpha) frame.oldAlpha = alpha or 1 end local function FCFTab_UpdateColors(tab, selected) if not tab then return end if tab:GetParent() == _G.ChatConfigFrameChatTabManager then if selected then tab.Text:SetTextColor(1, 1, 1) end local name = GetChatWindowInfo(tab:GetID()) if name then tab.Text:SetText(name) end tab:SetAlpha(1) -- for some reason blizzard likes to change the alpha here? idk else -- actual chat tab and other local chat = GetOwner(tab) if not chat then return end tab.selected = selected local whisper = tab.conversationIcon and chat.chatTarget local name = chat.name or UNKNOWN if whisper and not tab.whisperName then tab.whisperName = gsub(name, '([%S]-)%-[%S]+', '%1|cFF999999*|r') end if selected then if options.tabSelector == 'NONE' then tab:SetFormattedText(rChatPlus.TabStyles.NONE, tab.whisperName or name) else local color = options.tabSelectorColor local hexColor = L.RGBToHex(color.r, color.g, color.b) tab:SetFormattedText(rChatPlus.TabStyles[options.tabSelector] or rChatPlus.TabStyles.ARROW1, hexColor, tab.whisperName or name, hexColor) end if options.tabSelectedTextEnabled then local color = options.tabSelectedTextColor tab.Text:SetTextColor(color.r, color.g, color.b) return -- using selected text color end end if whisper then if not selected then tab:SetText(tab.whisperName or name) end else if not selected then tab:SetText(name) end end end end local function FCFDock_SelectWindow(_, chatFrame) if chatFrame then UpdateEditboxFont(chatFrame) end end local function Unsnapped(chat) if chat == rChatPlus.LeftChatWindow then rChatPlus.LeftChatWindow = nil elseif chat == rChatPlus.RightChatWindow then rChatPlus.RightChatWindow = nil end end local function ClearSnapping() rChatPlus.LeftChatWindow = nil rChatPlus.RightChatWindow = nil end local function SnappingChanged(chat) Unsnapped(chat) if chat == _G.GeneralDockManager.primary then for _, frame in ipairs(_G.GeneralDockManager.DOCKED_CHAT_FRAMES) do PositionChat(frame) end else PositionChat(chat) end end local function BuildCopyChatFrame() local frame = CreateFrame('Frame', 'CopyChatFrame', UIParent, 'BackdropTemplate') tinsert(_G.UISpecialFrames, 'CopyChatFrame') frame.backdrop = L.CreateBackdrop(frame) frame:SetSize(700, 200) frame:SetPoint('CENTER', UIParent, 'CENTER') frame:Hide() frame:SetMovable(true) frame:EnableMouse(true) frame:SetResizable(true) frame:SetMinResize(350, 100) frame:SetScript('OnMouseDown', function(copyChat, button) if button == 'LeftButton' and not copyChat.isMoving then copyChat:StartMoving() copyChat.isMoving = true elseif button == 'RightButton' and not copyChat.isSizing then copyChat:StartSizing() copyChat.isSizing = true end end) frame:SetScript('OnMouseUp', function(copyChat, button) if button == 'LeftButton' and copyChat.isMoving then copyChat:StopMovingOrSizing() copyChat.isMoving = false elseif button == 'RightButton' and copyChat.isSizing then copyChat:StopMovingOrSizing() copyChat.isSizing = false end end) frame:SetScript('OnHide', function(copyChat) if copyChat.isMoving or copyChat.isSizing then copyChat:StopMovingOrSizing() copyChat.isMoving = false copyChat.isSizing = false end end) frame:SetFrameStrata('DIALOG') local scrollArea = CreateFrame('ScrollFrame', 'CopyChatScrollFrame', frame, 'UIPanelScrollFrameTemplate') scrollArea:SetPoint('TOPLEFT', frame, 'TOPLEFT', 8, -30) scrollArea:SetPoint('BOTTOMRIGHT', frame, 'BOTTOMRIGHT', -30, 8) scrollArea:SetScript('OnSizeChanged', function(scroll) _G.CopyChatFrameEditBox:SetWidth(scroll:GetWidth()) _G.CopyChatFrameEditBox:SetHeight(scroll:GetHeight()) end) scrollArea:SetScript('OnVerticalScroll', function(scroll, offset) _G.CopyChatFrameEditBox:SetHitRectInsets(0, 0, offset, (_G.CopyChatFrameEditBox:GetHeight() - offset - scroll:GetHeight())) end) local editBox = CreateFrame('EditBox', 'CopyChatFrameEditBox', frame) editBox:SetMultiLine(true) editBox:SetMaxLetters(99999) editBox:EnableMouse(true) editBox:SetAutoFocus(false) editBox:SetFontObject(_G.ChatFontNormal) editBox:SetWidth(scrollArea:GetWidth()) editBox:SetHeight(200) editBox:SetScript('OnEscapePressed', function() _G.CopyChatFrame:Hide() end) scrollArea:SetScrollChild(editBox) _G.CopyChatFrameEditBox:SetScript('OnTextChanged', function(_, userInput) if userInput then return end local _, Max = _G.CopyChatScrollFrameScrollBar:GetMinMaxValues() for _ = 1, Max do _G.ScrollFrameTemplate_OnMouseWheel(_G.CopyChatScrollFrame, -1) end end) local close = CreateFrame('Button', 'CopyChatFrameCloseButton', frame, 'UIPanelCloseButton, BackdropTemplate') close:SetPoint('TOPRIGHT') close:SetFrameLevel(close:GetFrameLevel() + 1) close:EnableMouse(true) end function rChatPlus:Initialize() SetupChat() UpdateFading() Panels_ColorUpdate() HandleChatVoiceIcons() UpdateEditboxAnchors() hooksecurefunc("ChatEdit_SetLastActiveWindow", ChatEdit_SetLastActiveWindow) hooksecurefunc("ChatEdit_DeactivateChat", ChatEdit_DeactivateChat) hooksecurefunc("ChatEdit_ActivateChat", ChatEdit_ActivateChat) hooksecurefunc("ChatEdit_OnEnterPressed", ChatEdit_OnEnterPressed) hooksecurefunc("FCFDock_UpdateTabs", FCFDock_UpdateTabs) hooksecurefunc("FCF_Close", FCF_Close) hooksecurefunc("FCF_SetWindowAlpha", FCF_SetWindowAlpha) hooksecurefunc("FCFTab_UpdateColors", FCFTab_UpdateColors) hooksecurefunc('FCFDock_SelectWindow', FCFDock_SelectWindow) hooksecurefunc('FCF_SavePositionAndDimensions', SnappingChanged) hooksecurefunc('FCF_UnDockFrame', SnappingChanged) hooksecurefunc('FCF_DockFrame', SnappingChanged) hooksecurefunc('FCF_ResetChatWindows', ClearSnapping) hooksecurefunc('RedockChatWindows', ClearSnapping) self:RegisterEvent('UPDATE_CHAT_WINDOWS') self:RegisterEvent('UPDATE_FLOATING_CHAT_WINDOWS') self:SetScript('OnEvent', function(self, event) if event == 'UPDATE_CHAT_WINDOWS' or event == 'UPDATE_FLOATING_CHAT_WINDOWS' then SetupChat() end end) BuildCopyChatFrame() -- Editbox Backdrop Color hooksecurefunc('ChatEdit_UpdateHeader', function(editbox) local chatType = editbox:GetAttribute('chatType') if not chatType then return end local ChatTypeInfo = _G.ChatTypeInfo local info = ChatTypeInfo[chatType] local chanTarget = editbox:GetAttribute('channelTarget') local chanName = chanTarget and GetChannelName(chanTarget) --Increase inset on right side to make room for character count text local insetLeft, insetRight, insetTop, insetBottom = editbox:GetTextInsets() editbox:SetTextInsets(insetLeft, insetRight + 30, insetTop, insetBottom) if not editbox.backdrop then editbox.backdrop = L.CreateBackdrop(editbox) end if chanName and (chatType == 'CHANNEL') then if chanName == 0 then editbox.backdrop:SetBackdropBorderColor(unpack(options.backdrop.edgeColor)) else info = ChatTypeInfo[chatType..chanName] editbox.backdrop:SetBackdropBorderColor(info.r, info.g, info.b) end else editbox.backdrop:SetBackdropBorderColor(info.r, info.g, info.b) end end) end