diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs index c8ea692bb2..e4871f611e 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs @@ -40,7 +40,7 @@ namespace osu.Game.Tests.Visual.Navigation typeof(DashboardOverlay), typeof(NewsOverlay), typeof(ChannelManager), - typeof(ChatOverlayV2), + typeof(ChatOverlay), typeof(SettingsOverlay), typeof(UserProfileOverlay), typeof(BeatmapSetOverlay), diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs b/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs index 5d0116f80e..2ce914ba3d 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs @@ -86,9 +86,9 @@ namespace osu.Game.Tests.Visual.Navigation [Test] public void TestOverlaysAlwaysClosed() { - ChatOverlayV2 chat = null; + ChatOverlay chat = null; AddUntilStep("is at menu", () => Game.ScreenStack.CurrentScreen is MainMenu); - AddUntilStep("wait for chat load", () => (chat = Game.ChildrenOfType().SingleOrDefault()) != null); + AddUntilStep("wait for chat load", () => (chat = Game.ChildrenOfType().SingleOrDefault()) != null); AddStep("show chat", () => InputManager.Key(Key.F8)); diff --git a/osu.Game.Tests/Visual/Online/TestSceneChannelList.cs b/osu.Game.Tests/Visual/Online/TestSceneChannelList.cs index e4bc5645b6..39a4f1a8a1 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChannelList.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChannelList.cs @@ -87,7 +87,7 @@ namespace osu.Game.Tests.Visual.Online { leaveText.Text = $"OnRequestLeave: {channel.Name}"; leaveText.FadeOutFromOne(1000, Easing.InQuint); - selected.Value = null; + selected.Value = channelList.ChannelListingChannel; channelList.RemoveChannel(channel); }; @@ -112,6 +112,12 @@ namespace osu.Game.Tests.Visual.Online for (int i = 0; i < 10; i++) channelList.AddChannel(createRandomPrivateChannel()); }); + + AddStep("Add Announce Channels", () => + { + for (int i = 0; i < 2; i++) + channelList.AddChannel(createRandomAnnounceChannel()); + }); } [Test] @@ -170,5 +176,16 @@ namespace osu.Game.Tests.Visual.Online Username = $"test user {id}", }); } + + private Channel createRandomAnnounceChannel() + { + int id = RNG.Next(0, 10000); + return new Channel + { + Name = $"Announce {id}", + Type = ChannelType.Announce, + Id = id, + }; + } } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlayV2.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs similarity index 96% rename from osu.Game.Tests/Visual/Online/TestSceneChatOverlayV2.cs rename to osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index ba4db50a11..4edbb9f215 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlayV2.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -32,9 +32,9 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneChatOverlayV2 : OsuManualInputManagerTestScene + public class TestSceneChatOverlay : OsuManualInputManagerTestScene { - private TestChatOverlayV2 chatOverlay; + private TestChatOverlay chatOverlay; private ChannelManager channelManager; private APIUser testUser; @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.Online Children = new Drawable[] { channelManager, - chatOverlay = new TestChatOverlayV2(), + chatOverlay = new TestChatOverlay(), }, }; }); @@ -455,6 +455,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestKeyboardNextChannel() { + Channel announceChannel = createAnnounceChannel(); Channel pmChannel1 = createPrivateChannel(); Channel pmChannel2 = createPrivateChannel(); @@ -464,6 +465,7 @@ namespace osu.Game.Tests.Visual.Online channelManager.JoinChannel(testChannel2); channelManager.JoinChannel(pmChannel1); channelManager.JoinChannel(pmChannel2); + channelManager.JoinChannel(announceChannel); chatOverlay.Show(); }); @@ -477,6 +479,9 @@ namespace osu.Game.Tests.Visual.Online AddStep("Press document next keys", () => InputManager.Keys(PlatformAction.DocumentNext)); AddUntilStep("PM Channel 2 displayed", () => channelIsVisible && currentDrawableChannel?.Channel == pmChannel2); + AddStep("Press document next keys", () => InputManager.Keys(PlatformAction.DocumentNext)); + AddUntilStep("Announce channel displayed", () => channelIsVisible && currentDrawableChannel?.Channel == announceChannel); + AddStep("Press document next keys", () => InputManager.Keys(PlatformAction.DocumentNext)); waitForChannel1Visible(); } @@ -548,7 +553,18 @@ namespace osu.Game.Tests.Visual.Online }); } - private class TestChatOverlayV2 : ChatOverlayV2 + private Channel createAnnounceChannel() + { + int id = RNG.Next(0, 10000); + return new Channel + { + Name = $"Announce {id}", + Type = ChannelType.Announce, + Id = id, + }; + } + + private class TestChatOverlay : ChatOverlay { public bool SlowLoading { get; set; } diff --git a/osu.Game.Tests/Visual/Online/TestSceneMessageNotifier.cs b/osu.Game.Tests/Visual/Online/TestSceneMessageNotifier.cs index 46f426597a..79f62a16e3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneMessageNotifier.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneMessageNotifier.cs @@ -208,7 +208,7 @@ namespace osu.Game.Tests.Visual.Online }; [Cached] - public ChatOverlayV2 ChatOverlay { get; } = new ChatOverlayV2(); + public ChatOverlay ChatOverlay { get; } = new ChatOverlay(); private readonly MessageNotifier messageNotifier = new MessageNotifier(); diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 69e7dee1a5..20d555c16c 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -46,7 +46,7 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.RandomSelectAlgorithm, RandomSelectAlgorithm.RandomPermutation); - SetDefault(OsuSetting.ChatDisplayHeight, ChatOverlayV2.DEFAULT_HEIGHT, 0.2f, 1f); + SetDefault(OsuSetting.ChatDisplayHeight, ChatOverlay.DEFAULT_HEIGHT, 0.2f, 1f); SetDefault(OsuSetting.BeatmapListingCardSize, BeatmapCardSize.Normal); diff --git a/osu.Game/Online/Chat/MessageNotifier.cs b/osu.Game/Online/Chat/MessageNotifier.cs index cea3e321fa..ca6082e19b 100644 --- a/osu.Game/Online/Chat/MessageNotifier.cs +++ b/osu.Game/Online/Chat/MessageNotifier.cs @@ -27,7 +27,7 @@ namespace osu.Game.Online.Chat private INotificationOverlay notifications { get; set; } [Resolved] - private ChatOverlayV2 chatOverlay { get; set; } + private ChatOverlay chatOverlay { get; set; } [Resolved] private ChannelManager channelManager { get; set; } @@ -170,7 +170,7 @@ namespace osu.Game.Online.Chat public override bool IsImportant => false; [BackgroundDependencyLoader] - private void load(OsuColour colours, ChatOverlayV2 chatOverlay, INotificationOverlay notificationOverlay) + private void load(OsuColour colours, ChatOverlay chatOverlay, INotificationOverlay notificationOverlay) { IconBackground.Colour = colours.PurpleDark; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 402bd94f31..785881d97a 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -75,7 +75,7 @@ namespace osu.Game public Toolbar Toolbar; - private ChatOverlayV2 chatOverlay; + private ChatOverlay chatOverlay; private ChannelManager channelManager; @@ -848,7 +848,7 @@ namespace osu.Game loadComponentSingleFile(news = new NewsOverlay(), overlayContent.Add, true); var rankingsOverlay = loadComponentSingleFile(new RankingsOverlay(), overlayContent.Add, true); loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal, true); - loadComponentSingleFile(chatOverlay = new ChatOverlayV2(), overlayContent.Add, true); + loadComponentSingleFile(chatOverlay = new ChatOverlay(), overlayContent.Add, true); loadComponentSingleFile(new MessageNotifier(), AddInternal, true); loadComponentSingleFile(Settings = new SettingsOverlay(), leftFloatingOverlayContent.Add, true); loadComponentSingleFile(changelogOverlay = new ChangelogOverlay(), overlayContent.Add, true); diff --git a/osu.Game/Overlays/Chat/ChannelList/ChannelList.cs b/osu.Game/Overlays/Chat/ChannelList/ChannelList.cs index ce1ed2b4d7..47a2d234d1 100644 --- a/osu.Game/Overlays/Chat/ChannelList/ChannelList.cs +++ b/osu.Game/Overlays/Chat/ChannelList/ChannelList.cs @@ -26,15 +26,20 @@ namespace osu.Game.Overlays.Chat.ChannelList public Action? OnRequestSelect; public Action? OnRequestLeave; - public IEnumerable Channels => publicChannelFlow.Channels.Concat(privateChannelFlow.Channels); + public IEnumerable Channels => groupFlow.Children + .OfType() + .SelectMany(channelGroup => channelGroup.ItemFlow) + .Select(item => item.Channel); public readonly ChannelListing.ChannelListingChannel ChannelListingChannel = new ChannelListing.ChannelListingChannel(); private readonly Dictionary channelMap = new Dictionary(); private OsuScrollContainer scroll = null!; - private ChannelListItemFlow publicChannelFlow = null!; - private ChannelListItemFlow privateChannelFlow = null!; + private FillFlowContainer groupFlow = null!; + private ChannelGroup announceChannelGroup = null!; + private ChannelGroup publicChannelGroup = null!; + private ChannelGroup privateChannelGroup = null!; private ChannelListItem selector = null!; [BackgroundDependencyLoader] @@ -49,25 +54,20 @@ namespace osu.Game.Overlays.Chat.ChannelList }, scroll = new OsuScrollContainer { - Padding = new MarginPadding { Vertical = 7 }, RelativeSizeAxes = Axes.Both, ScrollbarAnchor = Anchor.TopRight, ScrollDistance = 35f, - Child = new FillFlowContainer + Child = groupFlow = new FillFlowContainer { Direction = FillDirection.Vertical, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Children = new Drawable[] { - new ChannelListLabel(ChatStrings.ChannelsListTitlePUBLIC.ToUpper()), - publicChannelFlow = new ChannelListItemFlow(), - selector = new ChannelListItem(ChannelListingChannel) - { - Margin = new MarginPadding { Bottom = 10 }, - }, - new ChannelListLabel(ChatStrings.ChannelsListTitlePM.ToUpper()), - privateChannelFlow = new ChannelListItemFlow(), + announceChannelGroup = new ChannelGroup(ChatStrings.ChannelsListTitleANNOUNCE.ToUpper()), + publicChannelGroup = new ChannelGroup(ChatStrings.ChannelsListTitlePUBLIC.ToUpper()), + selector = new ChannelListItem(ChannelListingChannel), + privateChannelGroup = new ChannelGroup(ChatStrings.ChannelsListTitlePM.ToUpper()), }, }, }, @@ -85,9 +85,11 @@ namespace osu.Game.Overlays.Chat.ChannelList item.OnRequestSelect += chan => OnRequestSelect?.Invoke(chan); item.OnRequestLeave += chan => OnRequestLeave?.Invoke(chan); - ChannelListItemFlow flow = getFlowForChannel(channel); + FillFlowContainer flow = getFlowForChannel(channel); channelMap.Add(channel, item); flow.Add(item); + + updateVisibility(); } public void RemoveChannel(Channel channel) @@ -96,10 +98,12 @@ namespace osu.Game.Overlays.Chat.ChannelList return; ChannelListItem item = channelMap[channel]; - ChannelListItemFlow flow = getFlowForChannel(channel); + FillFlowContainer flow = getFlowForChannel(channel); channelMap.Remove(channel); flow.Remove(item); + + updateVisibility(); } public ChannelListItem GetItem(Channel channel) @@ -112,40 +116,58 @@ namespace osu.Game.Overlays.Chat.ChannelList public void ScrollChannelIntoView(Channel channel) => scroll.ScrollIntoView(GetItem(channel)); - private ChannelListItemFlow getFlowForChannel(Channel channel) + private FillFlowContainer getFlowForChannel(Channel channel) { switch (channel.Type) { case ChannelType.Public: - return publicChannelFlow; + return publicChannelGroup.ItemFlow; case ChannelType.PM: - return privateChannelFlow; + return privateChannelGroup.ItemFlow; + + case ChannelType.Announce: + return announceChannelGroup.ItemFlow; default: - return publicChannelFlow; + return publicChannelGroup.ItemFlow; } } - private class ChannelListLabel : OsuSpriteText + private void updateVisibility() { - public ChannelListLabel(LocalisableString label) - { - Text = label; - Margin = new MarginPadding { Left = 18, Bottom = 5 }; - Font = OsuFont.Torus.With(size: 12, weight: FontWeight.SemiBold); - } + if (announceChannelGroup.ItemFlow.Children.Count == 0) + announceChannelGroup.Hide(); + else + announceChannelGroup.Show(); } - private class ChannelListItemFlow : FillFlowContainer + private class ChannelGroup : FillFlowContainer { - public IEnumerable Channels => Children.Select(c => c.Channel); + public readonly FillFlowContainer ItemFlow; - public ChannelListItemFlow() + public ChannelGroup(LocalisableString label) { Direction = FillDirection.Vertical; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; + Padding = new MarginPadding { Top = 8 }; + + Children = new Drawable[] + { + new OsuSpriteText + { + Text = label, + Margin = new MarginPadding { Left = 18, Bottom = 5 }, + Font = OsuFont.Torus.With(size: 12, weight: FontWeight.SemiBold), + }, + ItemFlow = new FillFlowContainer + { + Direction = FillDirection.Vertical, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + }; } } } diff --git a/osu.Game/Overlays/Chat/ChatTextBar.cs b/osu.Game/Overlays/Chat/ChatTextBar.cs index 4dc609acd1..5100959eeb 100644 --- a/osu.Game/Overlays/Chat/ChatTextBar.cs +++ b/osu.Game/Overlays/Chat/ChatTextBar.cs @@ -141,8 +141,8 @@ namespace osu.Game.Overlays.Chat switch (newChannel?.Type) { - case ChannelType.Public: - chattingText.Text = ChatStrings.TalkingIn(newChannel.Name); + case null: + chattingText.Text = string.Empty; break; case ChannelType.PM: @@ -150,7 +150,7 @@ namespace osu.Game.Overlays.Chat break; default: - chattingText.Text = string.Empty; + chattingText.Text = ChatStrings.TalkingIn(newChannel.Name); break; } }, true); diff --git a/osu.Game/Overlays/ChatOverlayV2.cs b/osu.Game/Overlays/ChatOverlay.cs similarity index 98% rename from osu.Game/Overlays/ChatOverlayV2.cs rename to osu.Game/Overlays/ChatOverlay.cs index f2ec007b19..02769b5d68 100644 --- a/osu.Game/Overlays/ChatOverlayV2.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -27,7 +27,7 @@ using osu.Game.Overlays.Chat.Listing; namespace osu.Game.Overlays { - public class ChatOverlayV2 : OsuFocusedOverlayContainer, INamedOverlayComponent, IKeyBindingHandler + public class ChatOverlay : OsuFocusedOverlayContainer, INamedOverlayComponent, IKeyBindingHandler { public string IconTexture => "Icons/Hexacons/messaging"; public LocalisableString Title => ChatStrings.HeaderTitle; @@ -70,7 +70,7 @@ namespace osu.Game.Overlays private readonly IBindableList availableChannels = new BindableList(); private readonly IBindableList joinedChannels = new BindableList(); - public ChatOverlayV2() + public ChatOverlay() { Height = DEFAULT_HEIGHT; diff --git a/osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs b/osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs index eafb453f75..e3dc5f818a 100644 --- a/osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs @@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Profile.Header.Components private UserProfileOverlay userOverlay { get; set; } [Resolved(CanBeNull = true)] - private ChatOverlayV2 chatOverlay { get; set; } + private ChatOverlay chatOverlay { get; set; } [Resolved] private IAPIProvider apiProvider { get; set; } diff --git a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs index 20f405aae2..2d3b33e9bc 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Toolbar } [BackgroundDependencyLoader(true)] - private void load(ChatOverlayV2 chat) + private void load(ChatOverlay chat) { StateContainer = chat; }