diff --git a/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs b/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs
index e4118a23b4..a391ec4066 100644
--- a/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs
+++ b/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs
@@ -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);
}
}
}
diff --git a/osu.Game/Localisation/NotificationsStrings.cs b/osu.Game/Localisation/NotificationsStrings.cs
index 3614ed9133..d72bb195ab 100644
--- a/osu.Game/Localisation/NotificationsStrings.cs
+++ b/osu.Game/Localisation/NotificationsStrings.cs
@@ -83,16 +83,6 @@ Please try changing your audio device to a working setting.");
///
public static LocalisableString LinkTypeNotSupported => new TranslatableString(getKey(@"unsupported_link_type"), @"This link type is not yet supported!");
- ///
- /// "You received a private message from '{0}'. Click to read it!"
- ///
- public static LocalisableString PrivateMessageReceived(string username) => new TranslatableString(getKey(@"private_message_received"), @"You received a private message from '{0}'. Click to read it!", username);
-
- ///
- /// "Your name was mentioned in chat by '{0}'. Click to find out why!"
- ///
- 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);
-
///
/// "{0} invited you to the multiplayer match "{1}"! Click to join."
///
diff --git a/osu.Game/Online/Chat/MessageNotifier.cs b/osu.Game/Online/Chat/MessageNotifier.cs
index 49304c93a3..a8d6746b10 100644
--- a/osu.Game/Online/Chat/MessageNotifier.cs
+++ b/osu.Game/Online/Chat/MessageNotifier.cs
@@ -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));
}
///
/// Checks if mentions .
/// This will match against the case where underscores are used instead of spaces (which is how osu-stable handles usernames with spaces).
///
- 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
{
diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs
index 20c3b26b8b..427d874f12 100644
--- a/osu.Game/Overlays/Chat/ChatLine.cs
+++ b/osu.Game/Overlays/Chat/ChatLine.cs
@@ -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);