diff --git a/Realtime/Internal/Controller/LCIMMessageController.cs b/Realtime/Internal/Controller/LCIMMessageController.cs index 11ec039..830328f 100644 --- a/Realtime/Internal/Controller/LCIMMessageController.cs +++ b/Realtime/Internal/Controller/LCIMMessageController.cs @@ -56,7 +56,7 @@ namespace LeanCloud.Realtime.Internal.Controller { // 消息发送应答 AckCommand ack = response.AckMessage; message.Id = ack.Uid; - message.DeliveredTimestamp = ack.T; + message.SentTimestamp = ack.T; return message; } @@ -72,7 +72,10 @@ namespace LeanCloud.Realtime.Internal.Controller { PatchItem item = new PatchItem { Cid = convId, Mid = message.Id, - Recall = true + From = Client.Id, + Recall = true, + Timestamp = message.SentTimestamp, + PatchTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), }; patch.Patches.Add(item); GenericCommand request = NewCommand(CommandType.Patch, OpType.Modify); @@ -94,8 +97,10 @@ namespace LeanCloud.Realtime.Internal.Controller { PatchItem item = new PatchItem { Cid = convId, Mid = oldMessage.Id, - Timestamp = oldMessage.DeliveredTimestamp, + From = Client.Id, Recall = false, + Timestamp = oldMessage.SentTimestamp, + PatchTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), }; if (newMessage is LCIMTypedMessage typedMessage) { item.Data = JsonConvert.SerializeObject(typedMessage.Encode()); @@ -218,6 +223,41 @@ namespace LeanCloud.Realtime.Internal.Controller { #region 消息处理 internal override async Task OnNotification(GenericCommand notification) { + if (notification.Cmd == CommandType.Patch) { + await OnMessagePatched(notification); + } else if (notification.Cmd == CommandType.Direct) { + await OnMessaage(notification); + } + } + + private async Task OnMessagePatched(GenericCommand notification) { + PatchCommand patchMessage = notification.PatchMessage; + foreach (PatchItem patch in patchMessage.Patches) { + // 获取对话 + LCIMConversation conversation = await Client.GetOrQueryConversation(patch.Cid); + LCIMMessage message; + if (patch.HasBinaryMsg) { + byte[] bytes = patch.BinaryMsg.ToByteArray(); + message = LCIMBinaryMessage.Deserialize(bytes); + } else { + message = LCIMTypedMessage.Deserialize(patch.Data); + } + message.ConversationId = patch.Cid; + message.Id = patch.Mid; + message.FromClientId = patch.From; + message.SentTimestamp = patch.Timestamp; + message.PatchedTimestamp = patch.PatchTimestamp; + if (message is LCIMRecalledMessage recalledMessage) { + // 消息撤回 + Client.OnMessageRecalled?.Invoke(conversation, recalledMessage); + } else { + // 消息修改 + Client.OnMessageUpdated?.Invoke(conversation, message); + } + } + } + + private async Task OnMessaage(GenericCommand notification) { DirectCommand direct = notification.DirectMessage; // 反序列化消息 LCIMMessage message; diff --git a/Realtime/Internal/Controller/LCIMSessionController.cs b/Realtime/Internal/Controller/LCIMSessionController.cs index 6017ca6..f0c5353 100644 --- a/Realtime/Internal/Controller/LCIMSessionController.cs +++ b/Realtime/Internal/Controller/LCIMSessionController.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using LeanCloud.Storage; using LeanCloud.Realtime.Protocol; namespace LeanCloud.Realtime.Internal.Controller { @@ -23,6 +22,7 @@ namespace LeanCloud.Realtime.Internal.Controller { internal async Task Open(bool force) { SessionCommand session = await NewSessionCommand(); session.R = !force; + session.ConfigBitmap = 0x7B; GenericCommand request = NewCommand(CommandType.Session, OpType.Open); request.SessionMessage = session; GenericCommand response = await Client.Connection.SendRequest(request); diff --git a/Realtime/LCIMClient.cs b/Realtime/LCIMClient.cs index 6e87afd..a5e7c24 100644 --- a/Realtime/LCIMClient.cs +++ b/Realtime/LCIMClient.cs @@ -165,7 +165,7 @@ namespace LeanCloud.Realtime { /// /// 消息被撤回 /// - public Action OnMessageRecalled { + public Action OnMessageRecalled { get; set; } @@ -449,6 +449,7 @@ namespace LeanCloud.Realtime { _ = ConversationController.OnNotification(notification); break; case CommandType.Direct: + case CommandType.Patch: _ = MessageController.OnNotification(notification); break; case CommandType.Unread: diff --git a/Realtime/Message/LCIMMessage.cs b/Realtime/Message/LCIMMessage.cs index 786c229..77fc128 100644 --- a/Realtime/Message/LCIMMessage.cs +++ b/Realtime/Message/LCIMMessage.cs @@ -9,6 +9,7 @@ namespace LeanCloud.Realtime { internal const int VideoMessageType = -4; internal const int LocationMessageType = -5; internal const int FileMessageType = -6; + internal const int RecalledMessageType = -127; public string ConversationId { get; set; diff --git a/Realtime/Message/LCIMRecalledMessage.cs b/Realtime/Message/LCIMRecalledMessage.cs index a54d243..3706dda 100644 --- a/Realtime/Message/LCIMRecalledMessage.cs +++ b/Realtime/Message/LCIMRecalledMessage.cs @@ -1,7 +1,12 @@  namespace LeanCloud.Realtime { - public class LCIMRecalledMessage { + /// + /// 撤回消息 + /// + public class LCIMRecalledMessage : LCIMTypedMessage { public LCIMRecalledMessage() { } + + internal override int MessageType => RecalledMessageType; } } diff --git a/Realtime/Message/LCIMTypedMessage.cs b/Realtime/Message/LCIMTypedMessage.cs index fb0a61b..08a5d6d 100644 --- a/Realtime/Message/LCIMTypedMessage.cs +++ b/Realtime/Message/LCIMTypedMessage.cs @@ -52,24 +52,27 @@ namespace LeanCloud.Realtime { LCIMTypedMessage message = null; int msgType = (int)msgData["_lctype"]; switch (msgType) { - case -1: + case TextMessageType: message = new LCIMTextMessage(); break; - case -2: + case ImageMessageType: message = new LCIMImageMessage(); break; - case -3: + case AudioMessageType: message = new LCIMAudioMessage(); break; - case -4: + case VideoMessageType: message = new LCIMVideoMessage(); break; - case -5: + case LocationMessageType: message = new LCIMLocationMessage(); break; - case -6: + case FileMessageType: message = new LCIMFileMessage(); break; + case RecalledMessageType: + message = new LCIMRecalledMessage(); + break; default: // TODO 用户自定义类型消息