mirror of
https://github.com/ppy/osu.git
synced 2026-05-25 15:00:44 +08:00
Display user avatar and content in DM / mention notifications
This commit is contained in:
committed by
Dean Herbert
Unverified
parent
c2ace36348
commit
d796dee6fc
@@ -12,79 +12,79 @@ namespace osu.Game.Tests.Online.Chat
|
||||
[Test]
|
||||
public void TestContainsUsernameMidlinePositive()
|
||||
{
|
||||
Assert.IsTrue(MessageNotifier.CheckContainsUsername("This is a test message", "Test"));
|
||||
Assert.IsTrue(MessageNotifier.MatchUsername("This is a test message", "Test").Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestContainsUsernameStartOfLinePositive()
|
||||
{
|
||||
Assert.IsTrue(MessageNotifier.CheckContainsUsername("Test message", "Test"));
|
||||
Assert.IsTrue(MessageNotifier.MatchUsername("Test message", "Test").Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestContainsUsernameEndOfLinePositive()
|
||||
{
|
||||
Assert.IsTrue(MessageNotifier.CheckContainsUsername("This is a test", "Test"));
|
||||
Assert.IsTrue(MessageNotifier.MatchUsername("This is a test", "Test").Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestContainsUsernameMidlineNegative()
|
||||
{
|
||||
Assert.IsFalse(MessageNotifier.CheckContainsUsername("This is a testmessage for notifications", "Test"));
|
||||
Assert.IsFalse(MessageNotifier.MatchUsername("This is a testmessage for notifications", "Test").Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestContainsUsernameStartOfLineNegative()
|
||||
{
|
||||
Assert.IsFalse(MessageNotifier.CheckContainsUsername("Testmessage", "Test"));
|
||||
Assert.IsFalse(MessageNotifier.MatchUsername("Testmessage", "Test").Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestContainsUsernameEndOfLineNegative()
|
||||
{
|
||||
Assert.IsFalse(MessageNotifier.CheckContainsUsername("This is a notificationtest", "Test"));
|
||||
Assert.IsFalse(MessageNotifier.MatchUsername("This is a notificationtest", "Test").Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestContainsUsernameBetweenPunctuation()
|
||||
{
|
||||
Assert.IsTrue(MessageNotifier.CheckContainsUsername("Hello 'test'-message", "Test"));
|
||||
Assert.IsTrue(MessageNotifier.MatchUsername("Hello 'test'-message", "Test").Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestContainsUsernameUnicode()
|
||||
{
|
||||
Assert.IsTrue(MessageNotifier.CheckContainsUsername("Test \u0460\u0460 message", "\u0460\u0460"));
|
||||
Assert.IsTrue(MessageNotifier.MatchUsername("Test \u0460\u0460 message", "\u0460\u0460").Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestContainsUsernameUnicodeNegative()
|
||||
{
|
||||
Assert.IsFalse(MessageNotifier.CheckContainsUsername("Test ha\u0460\u0460o message", "\u0460\u0460"));
|
||||
Assert.IsFalse(MessageNotifier.MatchUsername("Test ha\u0460\u0460o message", "\u0460\u0460").Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestContainsUsernameSpecialCharactersPositive()
|
||||
{
|
||||
Assert.IsTrue(MessageNotifier.CheckContainsUsername("Test [#^-^#] message", "[#^-^#]"));
|
||||
Assert.IsTrue(MessageNotifier.MatchUsername("Test [#^-^#] message", "[#^-^#]").Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestContainsUsernameSpecialCharactersNegative()
|
||||
{
|
||||
Assert.IsFalse(MessageNotifier.CheckContainsUsername("Test pad[#^-^#]oru message", "[#^-^#]"));
|
||||
Assert.IsFalse(MessageNotifier.MatchUsername("Test pad[#^-^#]oru message", "[#^-^#]").Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestContainsUsernameAtSign()
|
||||
{
|
||||
Assert.IsTrue(MessageNotifier.CheckContainsUsername("@username hi", "username"));
|
||||
Assert.IsTrue(MessageNotifier.MatchUsername("@username hi", "username").Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestContainsUsernameColon()
|
||||
{
|
||||
Assert.IsTrue(MessageNotifier.CheckContainsUsername("username: hi", "username"));
|
||||
Assert.IsTrue(MessageNotifier.MatchUsername("username: hi", "username").Success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,16 +83,6 @@ Please try changing your audio device to a working setting.");
|
||||
/// </summary>
|
||||
public static LocalisableString LinkTypeNotSupported => new TranslatableString(getKey(@"unsupported_link_type"), @"This link type is not yet supported!");
|
||||
|
||||
/// <summary>
|
||||
/// "You received a private message from '{0}'. Click to read it!"
|
||||
/// </summary>
|
||||
public static LocalisableString PrivateMessageReceived(string username) => new TranslatableString(getKey(@"private_message_received"), @"You received a private message from '{0}'. Click to read it!", username);
|
||||
|
||||
/// <summary>
|
||||
/// "Your name was mentioned in chat by '{0}'. Click to find out why!"
|
||||
/// </summary>
|
||||
public static LocalisableString YourNameWasMentioned(string username) => new TranslatableString(getKey(@"your_name_was_mentioned"), @"Your name was mentioned in chat by '{0}'. Click to find out why!", username);
|
||||
|
||||
/// <summary>
|
||||
/// "{0} invited you to the multiplayer match "{1}"! Click to join."
|
||||
/// </summary>
|
||||
|
||||
@@ -11,11 +11,9 @@ using System.Text.RegularExpressions;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
@@ -136,59 +134,104 @@ namespace osu.Game.Online.Chat
|
||||
|
||||
private void checkForMentions(Channel channel, Message message)
|
||||
{
|
||||
if (!notifyOnUsername.Value || !CheckContainsUsername(message.Content, localUser.Value.Username)) return;
|
||||
if (!notifyOnUsername.Value)
|
||||
return;
|
||||
|
||||
notifications.Post(new MentionNotification(message, channel));
|
||||
var match = MatchUsername(message.Content, localUser.Value.Username);
|
||||
if (!match.Success)
|
||||
return;
|
||||
|
||||
notifications.Post(new MentionNotification(message, channel, match));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if <paramref name="message"/> mentions <paramref name="username"/>.
|
||||
/// This will match against the case where underscores are used instead of spaces (which is how osu-stable handles usernames with spaces).
|
||||
/// </summary>
|
||||
public static bool CheckContainsUsername(string message, string username)
|
||||
public static Match MatchUsername(string message, string username)
|
||||
{
|
||||
string fullName = Regex.Escape(username);
|
||||
string underscoreName = Regex.Escape(username.Replace(' ', '_'));
|
||||
return Regex.IsMatch(message, $@"(^|\W)({fullName}|{underscoreName})($|\W)", RegexOptions.IgnoreCase);
|
||||
return Regex.Match(message, $@"(^|\W)({fullName}|{underscoreName})($|\W)", RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
public partial class PrivateMessageNotification : HighlightMessageNotification
|
||||
public partial class PrivateMessageNotification : UserAvatarNotification
|
||||
{
|
||||
private readonly Message message;
|
||||
private readonly Channel channel;
|
||||
|
||||
public PrivateMessageNotification(Message message, Channel channel)
|
||||
: base(message, channel)
|
||||
{
|
||||
Icon = FontAwesome.Solid.Envelope;
|
||||
Text = NotificationsStrings.PrivateMessageReceived(message.Sender.Username);
|
||||
}
|
||||
}
|
||||
|
||||
public partial class MentionNotification : HighlightMessageNotification
|
||||
{
|
||||
public MentionNotification(Message message, Channel channel)
|
||||
: base(message, channel)
|
||||
{
|
||||
Icon = FontAwesome.Solid.At;
|
||||
Text = NotificationsStrings.YourNameWasMentioned(message.Sender.Username);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract partial class HighlightMessageNotification : SimpleNotification
|
||||
{
|
||||
public override string PopInSampleName => "UI/notification-mention";
|
||||
|
||||
protected HighlightMessageNotification(Message message, Channel channel)
|
||||
: base(message.Sender)
|
||||
{
|
||||
this.message = message;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ChatOverlay chatOverlay, INotificationOverlay notificationOverlay)
|
||||
{
|
||||
// Sane maximum height to avoid the notification becoming too tall on long messages.
|
||||
// The height is ballparked to display two lines.
|
||||
TextFlow.AutoSizeAxes = Axes.None;
|
||||
TextFlow.Height = 45;
|
||||
|
||||
TextFlow.ParagraphSpacing = 0.25f;
|
||||
TextFlow.AddParagraph(message.Sender.Username, s => s.Font = s.Font.With(weight: FontWeight.SemiBold));
|
||||
TextFlow.AddParagraph(message.Content);
|
||||
|
||||
Activated = delegate
|
||||
{
|
||||
notificationOverlay.Hide();
|
||||
chatOverlay.HighlightMessage(message, channel);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public partial class MentionNotification : UserAvatarNotification
|
||||
{
|
||||
public override string PopInSampleName => "UI/notification-mention";
|
||||
|
||||
private readonly Message message;
|
||||
private readonly Channel channel;
|
||||
private readonly Match match;
|
||||
|
||||
public MentionNotification(Message message, Channel channel, Match match)
|
||||
: base(message.Sender)
|
||||
{
|
||||
this.message = message;
|
||||
this.channel = channel;
|
||||
this.match = match;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours, ChatOverlay chatOverlay, INotificationOverlay notificationOverlay)
|
||||
private void load(ChatOverlay chatOverlay, INotificationOverlay notificationOverlay, OverlayColourProvider colourProvider)
|
||||
{
|
||||
IconContent.Colour = colours.PurpleDark;
|
||||
// Sane maximum height to avoid the notification becoming too tall on long messages.
|
||||
// The height is ballparked to display two lines.
|
||||
TextFlow.AutoSizeAxes = Axes.None;
|
||||
TextFlow.Height = 45;
|
||||
|
||||
TextFlow.ParagraphSpacing = 0.25f;
|
||||
TextFlow.AddText(message.Sender.Username, s => s.Font = s.Font.With(weight: FontWeight.SemiBold));
|
||||
TextFlow.AddText($" in {channel.Name}", s =>
|
||||
{
|
||||
s.Font = s.Font.With(weight: FontWeight.SemiBold);
|
||||
s.Colour = colourProvider.Content2;
|
||||
});
|
||||
|
||||
TextFlow.NewParagraph();
|
||||
|
||||
int start = match.Index;
|
||||
int end = match.Index + match.Length;
|
||||
|
||||
TextFlow.AddText(message.Content[..start]);
|
||||
TextFlow.AddText(message.Content[start..end], s =>
|
||||
{
|
||||
s.Font = s.Font.With(weight: FontWeight.SemiBold);
|
||||
s.Colour = colourProvider.Colour0;
|
||||
});
|
||||
TextFlow.AddText(message.Content[end..]);
|
||||
|
||||
Activated = delegate
|
||||
{
|
||||
|
||||
@@ -292,7 +292,7 @@ namespace osu.Game.Overlays.Chat
|
||||
// remove non-existent channels from the link list
|
||||
message.Links.RemoveAll(link => link.Action == LinkAction.OpenChannel && chatManager?.AvailableChannels.Any(c => c.Name == link.Argument.ToString()) != true);
|
||||
|
||||
isMention = MessageNotifier.CheckContainsUsername(message.DisplayContent, api.LocalUser.Value.Username);
|
||||
isMention = MessageNotifier.MatchUsername(message.DisplayContent, api.LocalUser.Value.Username).Success;
|
||||
|
||||
drawableContentFlow.Clear();
|
||||
drawableContentFlow.AddLinks(message.DisplayContent, message.Links);
|
||||
|
||||
Reference in New Issue
Block a user