Quantcast Code optimization and issue with hyperlinks in chat - WoWInterface
Thread Tools Display Modes
10-11-18, 06:50 PM   #1
Terenna
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jun 2016
Posts: 33
Code optimization and issue with hyperlinks in chat

Good evening everyone,

I'm playing around with how the chat appears. I've learned how incredibly complex the chat frame is, but I'm running into an issue I can't yet figure out.

The following code modifies how the chat appears to my liking. It works in all regards except one, if I link an item or achievement or someother hyperlink into chat, and have string(s) after the hyperlink, the color of the strings after the hyperlink turns white.

To put this in perspective, I would type "Wow look at this item: (shift click item). It's got amazing stats." and this would appear: Wow look at this item: [Sick DPS Weapon]. It's got amazing stats.

I can't for the life of me figure out why a hyperlink would cause an escape from the color sequence, or how I could get around it. If anyone has a suggestion on how to fix this, or sees a way to better optimize my code, please let me know:

Lua Code:
  1. local function RGBPercToHex(r, g, b)
  2.     r = r <= 1 and r >= 0 and r or 0
  3.     g = g <= 1 and g >= 0 and g or 0
  4.     b = b <= 1 and b >= 0 and b or 0
  5.     return string.format('%02x%02x%02x', r*255, g*255, b*255)
  6. end
  7.  
  8. ChatFrame_AddMessageEventFilter('CHAT_MSG_CHANNEL', function() return true end)
  9. local f = CreateFrame('frame')
  10. f:RegisterEvent('CHAT_MSG_CHANNEL')
  11. f:SetScript('OnEvent', function(self, event, ...)
  12.     local type = strsub(event, 10)
  13.     local info = ChatTypeInfo[type]
  14.     local timeStamp
  15.     local chatMessage, sender, senderLanguage, fullChannelName, _, senderFlags, _, channelNumber, _, _, chatLineID, senderGUID = ...
  16.     local senderLinkDisplay = GetColoredName(event, ...)
  17.     local playerLink = GetPlayerLink(sender, senderLinkDisplay, chatLineID, Chat_GetChatCategory(type), tostring(channelNumber))
  18.  
  19.     --first we get the timestamp with time(), then we format it with blizz's style with BetterDate
  20.     --then we change the text color to a grey and add brackets and finally remove the annoying space that gets between the string and ]
  21.     timeStamp = gsub(string.format('|cff'..RGBPercToHex(0.5, 0.5, 0.5)..'[%s]|r', BetterDate(CHAT_TIMESTAMP_FORMAT, time())), ' ', '')
  22.  
  23.     --properly color our channel number and following .
  24.     channelNumber = string.format('|cff'..RGBPercToHex(info.r, info.g, info.b)..'%s|r', channelNumber)
  25.  
  26.     --properly color our chat message in whatever channel it is
  27.     chatMessage = string.format('|cff'..RGBPercToHex(info.r, info.g, info.b)..'%s|r', chatMessage)
  28.  
  29.     --this block of code will search the chat for mentions of character's full name and change it to their class color
  30.     local test = chatMessage:gsub('[^a-zA-Z%s]', '')
  31.     local words = {strsplit(' ', test)}
  32.     for i = 1, #words do
  33.         --since we technically just changed our sentence or word to ff000000wordr or ff000000this is my sentencer
  34.         --we need to truncate the last word's trailing r and first word's hexcode
  35.         if i == 1 then
  36.             words[i] = strsub(words[i], 8) --cut off the opening timestamp color hexcode
  37.             if i == #words then
  38.                 words[i] = words[i]:sub(1, -1) --a one word message with a player name was said, now cut off the closing r, too
  39.             end
  40.         elseif i == #words then
  41.             words[i] = words[i]:sub(1, -1) --cut off the closing r
  42.         end
  43.         local w = words[i]
  44.         if (w and not (w == 'player' or w == 'target') and UnitName(w) and UnitIsPlayer(w)) then
  45.             local _, class = UnitClass(w)
  46.             local colors = RAID_CLASS_COLORS[class]
  47.             if (colors) then --replace the words that match player names with class colors, return back to the channel color for the next word(s)
  48.                 chatMessage = gsub(chatMessage, w, '|cff'..RGBPercToHex(colors.r, colors.g, colors.b)..'%1|r|cff'..RGBPercToHex(info.r, info.g, info.b))
  49.             end
  50.         end
  51.     end
  52.     chatMessage = timeStamp..' '..channelNumber..'. '..playerLink..': '..chatMessage
  53.  
  54.     ChatFrame1:AddMessage(chatMessage)
  55. end)

Last edited by Terenna : 10-11-18 at 07:36 PM.
  Reply With Quote
10-11-18, 07:35 PM   #2
Terenna
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jun 2016
Posts: 33
I was able to come up with a shitty hack:

I switched

Lua Code:
  1. chatMessage = string.format('|cff'..RGBPercToHex(info.r, info.g, info.b)..'%s|r', chatMessage)

to

Lua Code:
  1. chatMessage = gsub(string.format('|cff'..RGBPercToHex(info.r, info.g, info.b)..'%s', chatMessage), '|h|r', '|h|r|cff'..RGBPercToHex(info.r, info.g, info.b))

which basically just looks for the return signature used by achievements, items, etc and replaces it with a hex open of our chat channel color
  Reply With Quote
10-12-18, 11:56 AM   #3
MuffinManKen
A Black Drake
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 81
If I'm understanding you correctly, you want to be able to set the text colour that's used by default in the chat frame and are jumping through hoops to make that work with colour encodings. But if that's what you're trying to do then it might be better to do that directly:

Lua Code:
  1. ChatFrame1:SetTextColor(r,g,b)

This way when things like links reset to default, it should be this colour.
  Reply With Quote
10-12-18, 01:24 PM   #4
Terenna
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jun 2016
Posts: 33
Thank for the reply; I appreciate you taking time to look at my code.

That would work if all the text in the ChatFrame# was going to be the same color. Like if I had dedicated tabs for each individual chat type. Currently I have all my chat in the main ChatFrame (ChatFrame1) so setting a default like that would make anything that wasn't that color appear incorrectly. I can understand the thought process since I'm only showing a function for CHAT_MSG_CHANNEL, but this was just my first trial run before I handled ALL the chat events. There's so many
  Reply With Quote
10-12-18, 02:09 PM   #5
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,726
This is what I use for url copy
Lua Code:
  1. local DefaultSetItemRef = SetItemRef
  2.  
  3. --we replace the default setitemref and use it to parse links for alt invite and url copy
  4. function SetItemRef(link, ...)
  5.   local type, value = link:match("(%a+):(.+)")
  6.   if IsAltKeyDown() and type == "player" then
  7.     InviteUnit(value:match("([^:]+)"))
  8.   elseif (type == "url") then
  9.     local eb = LAST_ACTIVE_CHAT_EDIT_BOX or ChatFrame1EditBox
  10.     if not eb then return end
  11.     eb:SetText(value)
  12.     eb:SetFocus()
  13.     eb:HighlightText()
  14.     if not eb:IsShown() then eb:Show() end
  15.   else
  16.     return DefaultSetItemRef(link, ...)
  17.   end
  18. end
  19.  
  20. --AddMessage
  21. local function AddMessage(self, text, ...)
  22.   --channel replace (Trade and such)
  23.   text = text:gsub('|h%[(%d+)%. .-%]|h', '|h%1.|h')
  24.   --url search
  25.   text = text:gsub('([wWhH][wWtT][wWtT][%.pP]%S+[^%p%s])', '|cffffffff|Hurl:%1|h[%1]|h|r')
  26.   return self.DefaultAddMessage(self, text, ...)
  27. end
  28.  
  29. --skin chat
  30. for i = 1, NUM_CHAT_WINDOWS do
  31.   local chatframe = _G["ChatFrame"..i]
  32.   --adjust channel display
  33.   if (i ~= 2) then
  34.     chatframe.DefaultAddMessage = chatframe.AddMessage
  35.     chatframe.AddMessage = AddMessage
  36.   end
  37. end

https://github.com/zorker/rothui/blo...rChat/core.lua
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW) | TDMOG

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)
  Reply With Quote
10-12-18, 02:56 PM   #6
Terenna
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jun 2016
Posts: 33
Zork, thank you for your comment. I was previously using your AddMessage and skinChat loop, however, I was running into issues with tainting the DefaultAddMessage portion of AddMessage and the replacement in the skinChat loop. I posted about it here: https://www.wowinterface.com/forums/...ad.php?t=56773 in case you were interested in what I was finding.

This is my (probably shitty) attempt at not tainting the new communities section by having to go through a very verbose method as I'm describing in this thread. That is, instead of simply taking control of the DefaultAddMessage and getting the taint, I have to filter ALL messages across all event types and properly "skin" their appearance.
  Reply With Quote
10-15-18, 01:50 AM   #7
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,726
Thanks. Yes replacing the default AddMessage and SetItemRef is bad since it can cause taint issues. Though I got no taints related to rChat yet.
If you have a working AddMessage and SetItemRef alternative that would be great.

Some code in the link is using
Lua Code:
  1. ChatFrame_AddMessageEventFilter('CHAT_MSG_CHANNEL', function() return true end)
Not sure if that makes sense when you can just remove the filter with
Lua Code:
  1. ChatFrame_RemoveMessageEventFilter (event, filter)
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW) | TDMOG

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)
  Reply With Quote
10-15-18, 03:48 AM   #8
Kanegasi
A Frostmaul Preserver
 
Kanegasi's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2007
Posts: 279
Originally Posted by zork View Post
Some code in the link is using
Lua Code:
  1. ChatFrame_AddMessageEventFilter('CHAT_MSG_CHANNEL', function() return true end)
Not sure if that makes sense when you can just remove the filter with
Lua Code:
  1. ChatFrame_RemoveMessageEventFilter (event, filter)
Terenna is recreating ChatFrame_MessageEventHandler, that filter is to completely block the original event while their new code handles it, otherwise you get double messages printed.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Code optimization and issue with hyperlinks in chat

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off