diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlayV2.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlayV2.cs index 82089ff3d1..3e3c8122b3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlayV2.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlayV2.cs @@ -5,6 +5,8 @@ using System; using System.Linq; using System.Collections.Generic; using System.Net; +using System.Threading; +using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -31,7 +33,7 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneChatOverlayV2 : OsuManualInputManagerTestScene { - private ChatOverlayV2 chatOverlay; + private TestChatOverlayV2 chatOverlay; private ChannelManager channelManager; private APIUser testUser; @@ -61,7 +63,7 @@ namespace osu.Game.Tests.Visual.Online Children = new Drawable[] { channelManager, - chatOverlay = new ChatOverlayV2 { RelativeSizeAxes = Axes.Both }, + chatOverlay = new TestChatOverlayV2 { RelativeSizeAxes = Axes.Both }, }, }; }); @@ -386,6 +388,34 @@ namespace osu.Game.Tests.Visual.Online AddAssert("TextBox is not focused", () => InputManager.FocusedDrawable == null); } + [Test] + public void TestSlowLoadingChannel() + { + AddStep("Show overlay (slow-loading)", () => + { + chatOverlay.Show(); + chatOverlay.SlowLoading = true; + }); + AddStep("Join channel 1", () => channelManager.JoinChannel(testChannel1)); + AddAssert("Channel 1 loading", () => !channelIsVisible && chatOverlay.GetSlowLoadingChannel(testChannel1).LoadState == LoadState.Loading); + + AddStep("Join channel 2", () => channelManager.JoinChannel(testChannel2)); + AddStep("Select channel 2", () => clickDrawable(getChannelListItem(testChannel2))); + AddAssert("Channel 2 loading", () => !channelIsVisible && chatOverlay.GetSlowLoadingChannel(testChannel2).LoadState == LoadState.Loading); + + AddStep("Finish channel 1 load", () => chatOverlay.GetSlowLoadingChannel(testChannel1).LoadEvent.Set()); + AddAssert("Channel 1 ready", () => chatOverlay.GetSlowLoadingChannel(testChannel1).LoadState == LoadState.Ready); + AddAssert("Channel 1 not displayed", () => !channelIsVisible); + + AddStep("Finish channel 2 load", () => chatOverlay.GetSlowLoadingChannel(testChannel2).LoadEvent.Set()); + AddAssert("Channel 2 loaded", () => chatOverlay.GetSlowLoadingChannel(testChannel2).IsLoaded); + AddAssert("Channel 2 displayed", () => channelIsVisible && currentDrawableChannel.Channel == testChannel2); + + AddStep("Select channel 1", () => clickDrawable(getChannelListItem(testChannel1))); + AddAssert("Channel 1 loaded", () => chatOverlay.GetSlowLoadingChannel(testChannel1).IsLoaded); + AddAssert("Channel 1 displayed", () => channelIsVisible && currentDrawableChannel.Channel == testChannel1); + } + private bool listingIsVisible => chatOverlay.ChildrenOfType().Single().State.Value == Visibility.Visible; @@ -432,5 +462,35 @@ namespace osu.Game.Tests.Visual.Online Topic = $"We talk about the number {id} here", Type = ChannelType.Public, }; + + private class TestChatOverlayV2 : ChatOverlayV2 + { + public bool SlowLoading { get; set; } + + public SlowLoadingDrawableChannel GetSlowLoadingChannel(Channel channel) => DrawableChannels.OfType().Single(c => c.Channel == channel); + + protected override ChatOverlayDrawableChannel CreateDrawableChannel(Channel newChannel) + { + return SlowLoading + ? new SlowLoadingDrawableChannel(newChannel) + : new ChatOverlayDrawableChannel(newChannel); + } + } + + private class SlowLoadingDrawableChannel : ChatOverlayDrawableChannel + { + public readonly ManualResetEventSlim LoadEvent = new ManualResetEventSlim(); + + public SlowLoadingDrawableChannel([NotNull] Channel channel) + : base(channel) + { + } + + [BackgroundDependencyLoader] + private void load() + { + LoadEvent.Wait(10000); + } + } } } diff --git a/osu.Game/Overlays/ChatOverlayV2.cs b/osu.Game/Overlays/ChatOverlayV2.cs index 611c539f8f..b2c1f6858c 100644 --- a/osu.Game/Overlays/ChatOverlayV2.cs +++ b/osu.Game/Overlays/ChatOverlayV2.cs @@ -41,6 +41,8 @@ namespace osu.Game.Overlays private readonly Dictionary loadedChannels = new Dictionary(); + protected IEnumerable DrawableChannels => loadedChannels.Values; + private readonly BindableFloat chatHeight = new BindableFloat(); private bool isDraggingTopBar; private float dragStartChatHeight; @@ -260,7 +262,7 @@ namespace osu.Game.Overlays loading.Show(); // Ensure the drawable channel is stored before async load to prevent double loading - ChatOverlayDrawableChannel drawableChannel = new ChatOverlayDrawableChannel(newChannel); + ChatOverlayDrawableChannel drawableChannel = CreateDrawableChannel(newChannel); loadedChannels.Add(newChannel, drawableChannel); LoadComponentAsync(drawableChannel, loadedDrawable => @@ -281,6 +283,8 @@ namespace osu.Game.Overlays } } + protected virtual ChatOverlayDrawableChannel CreateDrawableChannel(Channel newChannel) => new ChatOverlayDrawableChannel(newChannel); + private void joinedChannelsChanged(object sender, NotifyCollectionChangedEventArgs args) { switch (args.Action)