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/TestSceneChatOverlayV2.cs index ba4db50a11..5f237b4b2d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlayV2.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlayV2.cs @@ -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,6 +553,17 @@ namespace osu.Game.Tests.Visual.Online }); } + private Channel createAnnounceChannel() + { + int id = RNG.Next(0, 10000); + return new Channel + { + Name = $"Announce {id}", + Type = ChannelType.Announce, + Id = id, + }; + } + private class TestChatOverlayV2 : ChatOverlayV2 { public bool SlowLoading { get; set; } 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);