отремонтировал и анимировал смайлики для вебчатов

This commit is contained in:
PC1\PTyTb
2025-08-14 19:58:19 +03:00
parent 3ac578b6e6
commit bad576dd4d
10 changed files with 217 additions and 567 deletions
+89 -120
View File
@@ -8,7 +8,7 @@ uses
FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls,
System.Rtti, FMX.Grid.Style, FMX.Grid, FMX.ScrollBox, FMX.Edit, FMX.Colors,
FMX.ListBox, FMX.EditBox, FMX.SpinBox, FMX.Controls.Presentation, uRecords,
System.Generics.Defaults, fFontSettings;
System.Generics.Defaults, fFontSettings, System.Character;
type
TChatWebServers = record
@@ -117,125 +117,6 @@ begin
end;
end;
function TfrOBS.FindEmoteByID(const ID: string): TEmotes;
var
i: integer;
begin
result.ID := '';
if not Assigned(ChatEmotes) then
exit;
for i := 0 to ChatEmotes.Count - 1 do
if ChatEmotes[i].ID = ID then
begin
result := ChatEmotes[i];
Break;
end;
end;
function TfrOBS.ReplaceEmotesInMessage(const MessageText,
EmotesString: string): string;
type
TEmotePosition = record
StartPos: integer;
EndPos: integer;
ImageURL: string;
end;
var
Positions: Tlist<TEmotePosition>;
i, ColonPos: integer;
Parts, EmoteData, Ranges: tstringlist;
EmoteID, RangeStr: string;
StartPos, EndPos: integer;
Emote: TEmotes;
begin
result := MessageText;
if EmotesString.IsEmpty then
exit;
Parts := tstringlist.Create;
EmoteData := tstringlist.Create;
Ranges := tstringlist.Create;
Positions := Tlist<TEmotePosition>.Create;
try
Parts.Delimiter := '/';
Parts.StrictDelimiter := True;
Parts.DelimitedText := EmotesString;
for i := 0 to Parts.Count - 1 do
begin
ColonPos := Pos(':', Parts[i]);
if ColonPos = 0 then
Continue;
EmoteID := Copy(Parts[i], 1, ColonPos - 1);
RangeStr := Copy(Parts[i], ColonPos + 1, MaxInt);
Ranges.Clear;
Ranges.Delimiter := ',';
Ranges.StrictDelimiter := True;
Ranges.DelimitedText := RangeStr;
Emote := FindEmoteByID(EmoteID);
if Emote.ID = '' then
Continue;
for var j := 0 to Ranges.Count - 1 do
begin
EmoteData.Clear;
EmoteData.Delimiter := '-';
EmoteData.StrictDelimiter := True;
EmoteData.DelimitedText := Ranges[j];
if EmoteData.Count <> 2 then
Continue;
if TryStrToInt(EmoteData[0], StartPos) and
TryStrToInt(EmoteData[1], EndPos) then
begin
var
EmotePosition: TEmotePosition;
EmotePosition.StartPos := StartPos;
EmotePosition.EndPos := EndPos;
EmotePosition.ImageURL := Emote.images.Url1x;
Positions.Add(EmotePosition);
end;
end;
end;
Positions.Sort(TComparer<TEmotePosition>.Construct(
function(const Left, Right: TEmotePosition): integer
begin
result := Right.StartPos - Left.StartPos;
end));
var
SB := TStringBuilder.Create(MessageText);
try
for var Pos in Positions do
begin
if (Pos.StartPos < 0) or (Pos.EndPos >= SB.Length) or
(Pos.StartPos > Pos.EndPos) then
Continue;
var
Replacement := Format('<img src="%s" width="18" height="18">',
[Pos.ImageURL]);
SB.Remove(Pos.StartPos, Pos.EndPos - Pos.StartPos + 1);
SB.Insert(Pos.StartPos, Replacement);
end;
result := SB.ToString;
finally
SB.Free;
end;
finally
Parts.Free;
EmoteData.Free;
Ranges.Free;
Positions.Free;
end;
end;
function TfrOBS.GetBadgesHTML(Badges: string): string;
var
@@ -320,6 +201,78 @@ begin
end;
end;
function TfrOBS.ReplaceEmotesInMessage(const MessageText, EmotesString: string): string;
var
ProcessedEmotes: TDictionary<string, string>;
Parts: TStringList;
i, ColonPos: Integer;
EmoteID: string;
Emote: TEmotes;
ResultText: string;
begin
Result := MessageText;
if EmotesString.Trim = '' then
Exit;
// Èñïîëüçóåì ñëîâàðü äëÿ îòñëåæèâàíèÿ óæå îáðàáîòàííûõ ýìîäçè
ProcessedEmotes := TDictionary<string, string>.Create;
Parts := TStringList.Create;
try
// Ðàçäåëÿåì îáùóþ ñòðîêó ñìàéëîâ ïî '/'
Parts.StrictDelimiter := True;
Parts.Delimiter := '/';
Parts.DelimitedText := EmotesString;
ResultText := MessageText;
// Îáðàáàòûâàåì êàæäóþ ÷àñòü
for i := 0 to Parts.Count - 1 do
begin
ColonPos := Pos(':', Parts[i]);
if ColonPos = 0 then
Continue;
// Èçâëåêàåì ID ñìàéëà
EmoteID := Copy(Parts[i], 1, ColonPos - 1);
// Ïðîïóñêàåì åñëè óæå îáðàáàòûâàëè ýòîò ýìîäçè
if ProcessedEmotes.ContainsKey(EmoteID) then
Continue;
// Ïîëó÷àåì äàííûå ñìàéëà
Emote := FindEmoteByID(EmoteID);
if Emote.ID = '' then
Continue;
var imgUrl: string;
if Emote.topImage <> '' then
imgUrl := Emote.topImage
else if Emote.images.Url4x <> '' then
imgUrl := Emote.images.Url4x
else
Continue; // Ïðîïóñêàåì åñëè íåò URL
// Çàìåíÿåì âñå âõîæäåíèÿ èìåíè ýìîäçè
ResultText := StringReplace(
ResultText,
Emote.name,
Format('<img src="%s" width="18" height="18">', [imgUrl]),
[rfReplaceAll]
);
// Ïîìå÷àåì ýìîäçè êàê îáðàáîòàííûé
ProcessedEmotes.Add(EmoteID, '');
end;
Result := ResultText;
finally
ProcessedEmotes.Free;
Parts.Free;
end;
end;
procedure TfrOBS.AddChat(newRecord: TOBSChat);
begin
SetLength(listChats, Length(listChats) + 1);
@@ -613,6 +566,22 @@ begin
end;
end;
function TfrOBS.FindEmoteByID(const ID: string): TEmotes;
var
i: integer;
begin
result.ID := '';
if not Assigned(ChatEmotes) then
exit;
for i := 0 to ChatEmotes.Count - 1 do
if ChatEmotes[i].ID = ID then
begin
result := ChatEmotes[i];
Break;
end;
end;
procedure TfrOBS.sgWebChatsCellDblClick(const Column: TColumn;
const Row: integer);
var