diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 3e2a247d7f..3257774a27 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -44,7 +44,7 @@ namespace osu.Game.Online.Chat /// /// An event that fires when new messages arrived. /// - public event Action, bool> NewMessagesArrived; + public event Action> NewMessagesArrived; /// /// An event that fires when a pending message gets resolved. @@ -58,11 +58,6 @@ namespace osu.Game.Online.Chat public bool ReadOnly => false; //todo not yet used. - /// - /// Determines if the channel's previous messages have been loaded. - /// - public bool Populated { get; set; } = false; - public override string ToString() => Name; [JsonProperty(@"name")] @@ -110,7 +105,7 @@ namespace osu.Game.Online.Chat pendingMessages.Add(message); Messages.Add(message); - NewMessagesArrived?.Invoke(new[] { message }, Populated); + NewMessagesArrived?.Invoke(new[] { message }); } public bool MessagesLoaded; @@ -133,11 +128,8 @@ namespace osu.Game.Online.Chat purgeOldMessages(); - NewMessagesArrived?.Invoke(messages, Populated); + NewMessagesArrived?.Invoke(messages); } - - if (!Populated) - Populated = true; } /// diff --git a/osu.Game/Online/Chat/MessageNotifier.cs b/osu.Game/Online/Chat/MessageNotifier.cs index de079ce636..8663cf4793 100644 --- a/osu.Game/Online/Chat/MessageNotifier.cs +++ b/osu.Game/Online/Chat/MessageNotifier.cs @@ -51,7 +51,6 @@ namespace osu.Game.Online.Chat localUser = api.LocalUser; // Listen for new messages - channelManager.JoinedChannels.ItemsAdded += (joinedChannels) => { foreach (var channel in joinedChannels) @@ -65,14 +64,11 @@ namespace osu.Game.Online.Chat }; } - private void channel_NewMessagesArrived(IEnumerable messages, bool populated) + private void channel_NewMessagesArrived(IEnumerable messages) { if (messages == null || !messages.Any()) return; - if (!populated) - return; - HandleMessages(messages.First().ChannelId, messages); } @@ -94,7 +90,7 @@ namespace osu.Game.Online.Chat public void HandleMessages(Channel channel, IEnumerable messages) { - // don't show if visible or not visible + // don't show if the ChatOverlay and the channel is visible. if (IsActive && channelManager.CurrentChannel.Value == channel) return; @@ -108,26 +104,36 @@ namespace osu.Game.Online.Chat void onClick() { - chatOverlay.ScrollToAndHighlightMessage(channel, message); + notificationOverlay.Hide(); chatOverlay.Show(); + channelManager.CurrentChannel.Value = channel; } + + if (notifyOnChat.Value && channel.Type == ChannelType.PM) { - var existingNotification = notificationOverlay.Notifications.OfType().FirstOrDefault(n => n.Username == message.Sender.Username); + // Scheduling because of possible "race-condition" (NotificationOverlay didn't add the notification yet). + Schedule(() => + { + var existingNotification = notificationOverlay.Notifications.OfType() + .FirstOrDefault(n => n.Username == message.Sender.Username); - if (existingNotification == null) - { - var notification = new PrivateMessageNotification(message.Sender.Username, onClick); - notificationOverlay?.Post(notification); - } - else - { - existingNotification.MessageCount++; - } + if (existingNotification == null) + { + var notification = new PrivateMessageNotification(message.Sender.Username, onClick); + notificationOverlay?.Post(notification); + } + else + { + existingNotification.MessageCount++; + } + }); + continue; } + if (notifyOnMention.Value && anyCaseInsensitive(words, localUsername)) { var notification = new MentionNotification(message.Sender.Username, onClick); @@ -135,6 +141,7 @@ namespace osu.Game.Online.Chat continue; } + if (!string.IsNullOrWhiteSpace(highlightWords.Value)) { var matchedWord = hasCaseInsensitive(words, getWords(highlightWords.Value)); @@ -146,6 +153,40 @@ namespace osu.Game.Online.Chat } } } + + //making sure if the notification drawer bugs out, we merge it afterwards again. + Schedule(() => mergeNotifications()); + } + + /// + /// Checks current notifications if they aren't merged, and merges them together again. + /// + private void mergeNotifications() + { + if (notificationOverlay == null) + { + return; + } + + var pmn = notificationOverlay.Notifications.OfType(); + + foreach (var notification in pmn) + { + var duplicates = pmn.Where(n => n.Username == notification.Username); + + if (duplicates.Count() < 2) + continue; + + var first = duplicates.First(); + foreach (var notification2 in duplicates) + { + if (notification2 == first) + continue; + + first.MessageCount += notification2.MessageCount; + notification2.Close(); + } + } } private static string[] getWords(string input) => input.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); @@ -171,14 +212,12 @@ namespace osu.Game.Online.Chat public override bool IsImportant => false; [BackgroundDependencyLoader] - private void load(OsuColour colours, NotificationOverlay notificationOverlay) + private void load(OsuColour colours) { IconBackgound.Colour = colours.PurpleDark; Activated = delegate { - notificationOverlay.Hide(); onClick?.Invoke(); - return true; }; } @@ -202,6 +241,7 @@ namespace osu.Game.Online.Chat set { messageCount = value; + if (messageCount > 1) { Text = $"You received {messageCount} private messages from '{Username}'. Click to read it!"; @@ -220,15 +260,12 @@ namespace osu.Game.Online.Chat public override bool IsImportant => false; [BackgroundDependencyLoader] - private void load(OsuColour colours, NotificationOverlay notificationOverlay, ChatOverlay chatOverlay) + private void load(OsuColour colours) { IconBackgound.Colour = colours.PurpleDark; Activated = delegate { - notificationOverlay.Hide(); - chatOverlay.Show(); onClick?.Invoke(); - return true; }; } @@ -248,15 +285,12 @@ namespace osu.Game.Online.Chat public override bool IsImportant => false; [BackgroundDependencyLoader] - private void load(OsuColour colours, NotificationOverlay notificationOverlay, ChatOverlay chatOverlay) + private void load(OsuColour colours) { IconBackgound.Colour = colours.PurpleDark; Activated = delegate { - notificationOverlay.Hide(); - chatOverlay.Show(); onClick?.Invoke(); - return true; }; } diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 57ce7fed7c..9c75e89249 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -8,17 +8,12 @@ using System.Linq; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; using osu.Game.Online.Chat; -using osu.Game.Overlays.Notifications; using osu.Game.Graphics; -using osu.Game.Online.API; -using osu.Game.Configuration; -using osu.Game.Users; using osu.Game.Graphics.Sprites; using osu.Framework.Graphics; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Sprites; @@ -67,7 +62,7 @@ namespace osu.Game.Overlays.Chat }, }; - newMessagesArrived(Channel.Messages, Channel.Populated); + newMessagesArrived(Channel.Messages); Channel.NewMessagesArrived += newMessagesArrived; Channel.MessageRemoved += messageRemoved; @@ -97,7 +92,7 @@ namespace osu.Game.Overlays.Chat Colour = colours.ChatBlue.Lighten(0.7f), }; - private void newMessagesArrived(IEnumerable newMessages, bool populated) + private void newMessagesArrived(IEnumerable newMessages) { bool shouldScrollToEnd = scroll.IsScrolledToEnd(10) || !chatLines.Any() || newMessages.Any(m => m is LocalMessage); @@ -157,16 +152,6 @@ namespace osu.Game.Overlays.Chat } } - public void ScrollToAndHighlightMessage(Message message) - { - if (message is null) - return; - - var chatLine = findChatLine(message); - scroll.ScrollTo(chatLine); - chatLine.FlashColour(HighlightColour, 7500, Easing.InExpo); - } - private void messageRemoved(Message removed) { findChatLine(removed)?.FadeColour(Color4.Red, 400).FadeOut(600).Expire(); diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index ab74439f9a..c2716cd585 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -22,7 +22,6 @@ using osu.Game.Overlays.Chat.Selection; using osu.Game.Overlays.Chat.Tabs; using osuTK.Input; using osu.Framework.Graphics.Sprites; -using System; namespace osu.Game.Overlays { @@ -61,8 +60,6 @@ namespace osu.Game.Overlays private Container channelSelectionContainer; protected ChannelSelectionOverlay ChannelSelectionOverlay; - private Message highlightingMessage { get; set; } - public override bool Contains(Vector2 screenSpacePos) => chatContainer.ReceivePositionalInputAt(screenSpacePos) || (ChannelSelectionOverlay.State.Value == Visibility.Visible && ChannelSelectionOverlay.ReceivePositionalInputAt(screenSpacePos)); @@ -255,14 +252,16 @@ namespace osu.Game.Overlays if (ChannelTabControl.Current.Value != e.NewValue) Scheduler.Add(() => ChannelTabControl.Current.Value = e.NewValue); - var loaded = GetChannelDrawable(e.NewValue); + var loaded = loadedChannels.Find(drawable => drawable.Channel == e.NewValue); if (loaded == null) { currentChannelContainer.FadeOut(500, Easing.OutQuint); loading.Show(); - loaded = loadChannelDrawable(e.NewValue); + loaded = new DrawableChannel(e.NewValue); + loadedChannels.Add(loaded); + LoadComponentAsync(loaded, l => { if (currentChannel.Value != e.NewValue) @@ -273,12 +272,6 @@ namespace osu.Game.Overlays currentChannelContainer.Clear(false); currentChannelContainer.Add(loaded); currentChannelContainer.FadeIn(500, Easing.OutQuint); - - if (highlightingMessage != null && highlightingMessage.ChannelId == e.NewValue.Id) - { - loaded.ScrollToAndHighlightMessage(highlightingMessage); - highlightingMessage = null; - } }); } else @@ -446,34 +439,6 @@ namespace osu.Game.Overlays textbox.Text = string.Empty; } - /// - /// Returns the loaded drawable for a channel. Creates new instance if is true. Otherwise returns null if not found. - /// - public DrawableChannel GetChannelDrawable(Channel channel, bool createIfUnloaded = false) - { - var result = loadedChannels.Find(drawable => drawable.Channel == channel); - - if (createIfUnloaded && result == null) - { - result = loadChannelDrawable(channel); - } - - return result; - } - - private DrawableChannel loadChannelDrawable(Channel channel) - { - var loaded = new DrawableChannel(channel); - loadedChannels.Add(loaded); - return loaded; - } - - public void ScrollToAndHighlightMessage(Channel channel, Message message) - { - highlightingMessage = message; - channelManager.CurrentChannel.Value = channel; - } - private class TabsArea : Container { // IsHovered is used