mirror of
https://github.com/ppy/osu.git
synced 2025-02-05 21:23:22 +08:00
Fix handling of local echo deduplication
This commit is contained in:
parent
4f8e912f06
commit
58396d49dc
@ -28,6 +28,7 @@ namespace osu.Game.Online.API.Requests
|
|||||||
req.AddParameter(@"target_id", user.Id.ToString());
|
req.AddParameter(@"target_id", user.Id.ToString());
|
||||||
req.AddParameter(@"message", message.Content);
|
req.AddParameter(@"message", message.Content);
|
||||||
req.AddParameter(@"is_action", message.IsAction.ToString().ToLowerInvariant());
|
req.AddParameter(@"is_action", message.IsAction.ToString().ToLowerInvariant());
|
||||||
|
req.AddParameter(@"uuid", message.Uuid);
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ namespace osu.Game.Online.API.Requests
|
|||||||
req.Method = HttpMethod.Post;
|
req.Method = HttpMethod.Post;
|
||||||
req.AddParameter(@"is_action", Message.IsAction.ToString().ToLowerInvariant());
|
req.AddParameter(@"is_action", Message.IsAction.ToString().ToLowerInvariant());
|
||||||
req.AddParameter(@"message", Message.Content);
|
req.AddParameter(@"message", Message.Content);
|
||||||
|
req.AddParameter(@"uuid", Message.Uuid);
|
||||||
|
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
@ -134,6 +134,14 @@ namespace osu.Game.Online.Chat
|
|||||||
/// <param name="messages"></param>
|
/// <param name="messages"></param>
|
||||||
public void AddNewMessages(params Message[] messages)
|
public void AddNewMessages(params Message[] messages)
|
||||||
{
|
{
|
||||||
|
foreach (var m in messages)
|
||||||
|
{
|
||||||
|
LocalEchoMessage localEcho = pendingMessages.FirstOrDefault(local => local.Uuid == m.Uuid);
|
||||||
|
|
||||||
|
if (localEcho != null)
|
||||||
|
ReplaceMessage(localEcho, m);
|
||||||
|
}
|
||||||
|
|
||||||
messages = messages.Except(Messages).ToArray();
|
messages = messages.Except(Messages).ToArray();
|
||||||
|
|
||||||
if (messages.Length == 0) return;
|
if (messages.Length == 0) return;
|
||||||
|
@ -85,8 +85,21 @@ namespace osu.Game.Online.Chat
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
connector.ChannelJoined += ch => Schedule(() => joinChannel(ch));
|
connector.ChannelJoined += ch => Schedule(() =>
|
||||||
|
{
|
||||||
|
var localChannel = getChannel(ch);
|
||||||
|
|
||||||
|
if (localChannel != ch)
|
||||||
|
{
|
||||||
|
localChannel.Joined.Value = true;
|
||||||
|
localChannel.Id = ch.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
joinChannel(localChannel);
|
||||||
|
});
|
||||||
|
|
||||||
connector.NewMessages += msgs => Schedule(() => addMessages(msgs));
|
connector.NewMessages += msgs => Schedule(() => addMessages(msgs));
|
||||||
|
|
||||||
connector.PresenceReceived += () => Schedule(() =>
|
connector.PresenceReceived += () => Schedule(() =>
|
||||||
{
|
{
|
||||||
if (!channelsInitialised)
|
if (!channelsInitialised)
|
||||||
@ -189,7 +202,8 @@ namespace osu.Game.Online.Chat
|
|||||||
Timestamp = DateTimeOffset.Now,
|
Timestamp = DateTimeOffset.Now,
|
||||||
ChannelId = target.Id,
|
ChannelId = target.Id,
|
||||||
IsAction = isAction,
|
IsAction = isAction,
|
||||||
Content = text
|
Content = text,
|
||||||
|
Uuid = Guid.NewGuid().ToString()
|
||||||
};
|
};
|
||||||
|
|
||||||
target.AddLocalEcho(message);
|
target.AddLocalEcho(message);
|
||||||
@ -199,13 +213,7 @@ namespace osu.Game.Online.Chat
|
|||||||
{
|
{
|
||||||
var createNewPrivateMessageRequest = new CreateNewPrivateMessageRequest(target.Users.First(), message);
|
var createNewPrivateMessageRequest = new CreateNewPrivateMessageRequest(target.Users.First(), message);
|
||||||
|
|
||||||
createNewPrivateMessageRequest.Success += createRes =>
|
createNewPrivateMessageRequest.Success += _ => dequeueAndRun();
|
||||||
{
|
|
||||||
target.Id = createRes.ChannelID;
|
|
||||||
target.ReplaceMessage(message, createRes.Message);
|
|
||||||
dequeueAndRun();
|
|
||||||
};
|
|
||||||
|
|
||||||
createNewPrivateMessageRequest.Failure += exception =>
|
createNewPrivateMessageRequest.Failure += exception =>
|
||||||
{
|
{
|
||||||
handlePostException(exception);
|
handlePostException(exception);
|
||||||
@ -219,12 +227,7 @@ namespace osu.Game.Online.Chat
|
|||||||
|
|
||||||
var req = new PostMessageRequest(message);
|
var req = new PostMessageRequest(message);
|
||||||
|
|
||||||
req.Success += m =>
|
req.Success += m => dequeueAndRun();
|
||||||
{
|
|
||||||
target.ReplaceMessage(message, m);
|
|
||||||
dequeueAndRun();
|
|
||||||
};
|
|
||||||
|
|
||||||
req.Failure += exception =>
|
req.Failure += exception =>
|
||||||
{
|
{
|
||||||
handlePostException(exception);
|
handlePostException(exception);
|
||||||
@ -403,7 +406,20 @@ namespace osu.Game.Online.Chat
|
|||||||
{
|
{
|
||||||
Channel found = null;
|
Channel found = null;
|
||||||
|
|
||||||
bool lookupCondition(Channel ch) => lookup.Id > 0 ? ch.Id == lookup.Id : lookup.Name == ch.Name;
|
bool lookupCondition(Channel ch)
|
||||||
|
{
|
||||||
|
// If both channels have an id, use that.
|
||||||
|
if (lookup.Id > 0 && ch.Id > 0)
|
||||||
|
return ch.Id == lookup.Id;
|
||||||
|
|
||||||
|
// In the case that the local echo is received in a new channel (i.e. one that does not yet have an ID),
|
||||||
|
// then we need to check for any existing channel with the message containing the same message matched by UUID.
|
||||||
|
if (lookup.Messages.Count > 0 && ch.Messages.Any(m => m.Uuid == lookup.Messages.Last().Uuid))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// As a last resort, fallback to matching by name.
|
||||||
|
return lookup.Name == ch.Name;
|
||||||
|
}
|
||||||
|
|
||||||
var available = AvailableChannels.FirstOrDefault(lookupCondition);
|
var available = AvailableChannels.FirstOrDefault(lookupCondition);
|
||||||
if (available != null)
|
if (available != null)
|
||||||
|
@ -37,6 +37,12 @@ namespace osu.Game.Online.Chat
|
|||||||
set => Sender = new APIUser { Id = value };
|
set => Sender = new APIUser { Id = value };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A unique identifier for this message. Sent to and from osu!web to use for deduplication.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(@"uuid")]
|
||||||
|
public string Uuid { get; set; } = string.Empty;
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
public Message()
|
public Message()
|
||||||
{
|
{
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -126,12 +124,10 @@ namespace osu.Game.Online.Notifications.WebSocket
|
|||||||
NewChatMessageData? messageData = JsonConvert.DeserializeObject<NewChatMessageData>(message.Data.ToString());
|
NewChatMessageData? messageData = JsonConvert.DeserializeObject<NewChatMessageData>(message.Data.ToString());
|
||||||
Debug.Assert(messageData != null);
|
Debug.Assert(messageData != null);
|
||||||
|
|
||||||
List<Message> messages = messageData.Messages.Where(m => m.Sender.OnlineID != api.LocalUser.Value.OnlineID).ToList();
|
foreach (var msg in messageData.Messages)
|
||||||
|
HandleJoinedChannel(new Channel(msg.Sender) { Id = msg.ChannelId, Messages = { msg } });
|
||||||
|
|
||||||
foreach (var msg in messages)
|
HandleMessages(messageData.Messages);
|
||||||
HandleJoinedChannel(new Channel(msg.Sender) { Id = msg.ChannelId });
|
|
||||||
|
|
||||||
HandleMessages(messages);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user