Sure..
try
// ChannelChat.ChatMessages.BeginUpdate;
MessageXML := newXMLDocument;
MessageXML.Encoding := 'utf8';
MessageXML.LoadFromXML(ChannelData);
MessageXML.Active := True;
try
if ZIMChannelType = 'public' then
SectionNode := MessageXML.ChildNodes.FindNode('pub_msg')
else
if ZIMChannelType = 'private' then
SectionNode := MessageXML.ChildNodes.FindNode('priv_msg')
else
if ZIMChannelType = 'direct' then
SectionNode := MessageXML.ChildNodes.FindNode('direct_msg');
except
SectionNode := nil;
end;
if SectionNode <> nil then
begin
ItemNode := SectionNode.ChildNodes['msg-timestamp'];
MsgUnixTime := StrToInt64Def(ItemNode.Text,0);
if MsgUnixTime = 0 then
begin
MsgUnixTime := DateTimeToUnix(NOW);
end
else
begin
MsgTimestamp := UnixToDateTime(MsgUnixTime);
LastMessageTimestamp := MsgUnixTime;
// Timestamps are in UTC, convert to local time
MsgTimestamp := MsgTimestamp - (ONE_MINUTE * TZ.Bias) - (ONE_MINUTE * TZ.DaylightBias);
end;
if SectionNode.ChildNodes['content-type'].Text <> 'channel-info' then
begin
TheMessageID := SectionNode.ChildNodes['message-id'].Text;
// Remember the first (oldest) messageid for requesting more messages and last (newest) messageids as the bookmark of when we left..
if LastMessageID = '' then
LastMessageID := TheMessageID
else
begin
TmpMessageID := Copy(LastMessageID,1,Pos('@',LastMessageID)-1);
LastMsgID := StrToInt64Def(TmpMessageID,-1);
TmpMessageID := Copy(TheMessageID,1,Pos('@',TheMessageID)-1);
ThisMsgID := StrToInt64Def(TmpMessageID,-1);
if ThisMsgID > LastMsgID then LastMessageID := TheMessageID;
end;
if FirstMessageID = '' then
FirstMessageID := TheMessageID
else
begin
TmpMessageID := Copy(FirstMessageID,1,Pos('@',FirstMessageID)-1);
FirstMsgID := StrToInt64Def(TmpMessageID,-1);
TmpMessageID := Copy(TheMessageID,1,Pos('@',TheMessageID)-1);
ThisMsgID := StrToInt64Def(TmpMessageID,-1);
if ThisMsgID < FirstMsgID then
begin
FirstMessageID := TheMessageID;
end;
end;
end;
if LastMessageID = TheMessageID then
begin
if (not Self.Focused) and (not ChannelChat.Focused) and (not ChannelChat.Parent.Focused) and (not EditMessage.Focused) and (not BtnAttachment.Focused) and (not BtnSend.Focused) then Self.Icon := ImageHolder.Picture.Icon;
end
else
Self.Icon := Application.Icon;
MsgSenderRealname := MIMEDecodeString(SectionNode.ChildNodes['sender-real-name'].Text);
MsgSenderUsername := MIMEDecodeString(SectionNode.ChildNodes['sender-username'].Text);
// For messages with large attachements, the <miniature> may be present and the <att_filename> will be present..
// The <att_filename> is the attachment-id needed for retrieving the file from the media archive
ItemNode := SectionNode.ChildNodes['content'];
MessageLine := diMime.MimeDecodeString(ItemNode.Text);
Scroll := True;
if SectionNode.ChildNodes['content-type'].Text = 'channel-info' then
begin
if SectionNode.ChildNodes['user-status'].Text = 'ENTER' then
begin
EnteringUser := MIMEDecodeString(SectionNode.ChildNodes['sender-username'].Text);
if lowercase(EnteringUser) <> ChannelClient.SSHUser then
begin
NewChatItem := ChannelChat.ChatMessages.Add;
NewChatItem.Timestamp := NOW;
NewChatItem.Title := 'User joined';
NewChatItem.Text := MsgSenderRealname + ' have joined the channel';
// NewChatItem.StatusPosition := cisBottomLeft;
NewChatItem.MessageLocation := cmlLeft;
NewChatItem.Fill.Color := gcWheat;
end;
end
else
if SectionNode.ChildNodes['user-status'].Text = 'LEAVE' then
begin
NewChatItem := ChannelChat.ChatMessages.Add;
NewChatItem.Timestamp := NOW;
NewChatItem.Title := 'User leave';
NewChatItem.Text := MsgSenderRealname + ' have left the channel';
// NewChatItem.StatusPosition := cisBottomLeft;
NewChatItem.MessageLocation := cmlLeft;
NewChatItem.Fill.Color := gcWheat;
end
else
if SectionNode.ChildNodes['user-status'].Text = 'INFOANSWER' then
begin
end
else
if SectionNode.ChildNodes['user-status'].Text = 'INFOREQ' then
begin
end
else
if SectionNode.ChildNodes['no-prior-messages'].Text <> '' then
begin
ArchiveStartReached := True;
ChannelChat.Header.Text := '--- no more messages in the archive ---';
end
else
if SectionNode.ChildNodes['end-of-archive'].Text <> '' then
begin
ArchiveEndReached := True;
ChannelChat.Footer.Visible := False;
end;
end
else
begin
// It's a real message, find out where in the sequence it's supposed to be, based on timestamp
NewChatItem := nil;
cmi := 0;
while (cmi < ChannelChat.ChatMessages.Count) and (NewChatItem = nil) do
begin
if MsgTimestamp < ChannelChat.ChatMessages.Items[cmi].Timestamp then
begin
NewChatItem := ChannelChat.ChatMessages.Insert(cmi);
if ChannelChat.SelectedItem <> nil then ChannelChat.SelectItem(ChannelChat.SelectedItem.Index+1);
end;
Inc(cmi);
end;
if NewChatItem = nil then
begin
NewChatItem := ChannelChat.ChatMessages.Add;
end;
if SectionNode.ChildNodes['att_filename'].Text <> '' then
begin
MsgMiniature := SectionNode.ChildNodes['miniature'].Text;
if MsgMiniature <> '' then
begin
NewChatItem.Bitmap := TTMSFNCBitmap.Create;
ImageDataStream := Base64DecodeToStream(MsgMiniature);
NewChatItem.Bitmap.LoadFromStream(ImageDataStream);
ImageDataStream.Free;
NewChatItem.BitmapName := SectionNode.ChildNodes['original_filename'].Text;
end;
NewChatItem.Timestamp := MsgTimestamp;
NewChatItem.Status := GetFileDesc(SectionNode.ChildNodes['original_filename'].Text);
// NewChatItem.Status := SectionNode.ChildNodes['att_filename'].Text; // Save the Attachment_id instead of the message_id
NewChatItem.DataString := SectionNode.ChildNodes['att_filename'].Text;
NewChatItem.Title := MsgSenderRealname;
NewChatItem.Text := MIMEDecodeString(SectionNode.ChildNodes['content'].Text);
NewChatItem.StatusPosition := cisBottomLeft;
end
else
begin
NewChatItem.Timestamp := MsgTimestamp;
NewChatItem.DataString := TheMessageID;
// NewChatItem.Status := 'Message';
NewChatItem.Title := MsgSenderRealname;
NewChatItem.Text := MIMEDecodeString(SectionNode.ChildNodes['content'].Text);
NewChatItem.StatusPosition := cisBottomLeft;
end;
if MsgSenderUsername = ChannelClient.SSHUser then
begin
NewChatItem.MessageLocation := cmlRight;
NewChatItem.TitleColor := clTeal;
NewChatItem.Fill.Color := $00FFAD5B;
end
else
begin
NewChatItem.MessageLocation := cmlLeft;
end;
end;
end
else
begin
if Pos('<chan_msg>',ChannelData) > 0 then
begin
// It's a message from the system
SectionNode := MessageXML.ChildNodes['chan_msg'];
if SectionNode <> nil then
begin
ItemNode := SectionNode.ChildNodes['msg-timestamp'];
MsgUnixTime := StrToInt64Def(ItemNode.Text,0);
if MsgUnixTime = 0 then MsgUnixTime := DateTimeToUnix(NOW);
MsgTimestamp := UnixToDateTime(MsgUnixTime);
LastMessageTimestamp := MsgUnixTime;
// Timestamps are in UTC, convert to local time
MsgTimestamp := MsgTimestamp - (ONE_MINUTE * TZ.Bias) - (ONE_MINUTE * TZ.DaylightBias);
MsgSenderRealname := MIMEDecodeString(SectionNode.ChildNodes['sender-real-name'].Text);
MsgSenderUsername := MIMEDecodeString(SectionNode.ChildNodes['sender-username'].Text);
NewChatItem := ChannelChat.ChatMessages.Add;
NewChatItem.Timestamp := MsgTimestamp;
NewChatItem.Status := TheMessageID; // Save the Attachment_id instead of the message_id
NewChatItem.Title := MsgSenderRealname;
NewChatItem.Text := MIMEDecodeString(SectionNode.ChildNodes['content'].Text);
NewChatItem.StatusPosition := cisBottomLeft;
NewChatItem.MessageLocation := cmlLeft;
NewChatItem.Fill.Color := clMaroon;
NewChatItem.TextColor := clCream;
if Pos('this channel have no retention',lowercase(NewChatItem.Text)) > 0 then ChannelChat.OnVScroll := nil;
end;
end;
end;
MessageXML.Active := False;
MessageXML := nil;
// ChannelChat.ChatMessages.EndUpdate;
if (MenuAutoscroll.Checked) and (NewChatItem <> nil) and (NewChatItem.Index > 0) then ChannelChat.ScrollToItem(NewChatItem.Index);
finally
end;
ChannelChat.StartReload;
ChannelChat.StopReload;
ChannelChat.Refresh;
if ChannelChat.ChatMessages.Count > 0 then ChannelChat.EnableInteraction;