mirror of
https://github.com/ppy/osu.git
synced 2024-11-06 06:57:39 +08:00
fix channel selector not being closed
This commit is contained in:
parent
2d07514a56
commit
6c8cc9728f
@ -0,0 +1,190 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Chat.Tabs;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneChatOverlayScenarios : ManualInputManagerTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(ChannelTabControl),
|
||||
typeof(ChannelTabItem),
|
||||
typeof(ChatOverlay),
|
||||
};
|
||||
|
||||
private TestChatOverlay chatOverlay;
|
||||
|
||||
[Cached]
|
||||
private ChannelManager channelManager = new ChannelManager();
|
||||
|
||||
private Channel channel1;
|
||||
private Channel channel2;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var availableChannels = (BindableList<Channel>)channelManager.AvailableChannels;
|
||||
|
||||
availableChannels.Add(channel1 = new Channel(new User()) { Name = "test1" });
|
||||
availableChannels.Add(channel2 = new Channel(new User()) { Name = "test2" });
|
||||
|
||||
Add(chatOverlay = new TestChatOverlay
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(1)
|
||||
});
|
||||
}
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("Leave channels", () =>
|
||||
{
|
||||
channelManager.LeaveChannel(channel1);
|
||||
channelManager.LeaveChannel(channel2);
|
||||
});
|
||||
AddStep("Hide chat", () => chatOverlay.Hide());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that if no maps are added, the channel selector is also toggled when <see cref="ChatOverlay"/> is toggled.
|
||||
/// Also check that both are properly closed when toggling again.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestToggleChatWithNoChannelsJoined()
|
||||
{
|
||||
AddStep("Toggle chat overlay", () => chatOverlay.Show());
|
||||
AddAssert("Channel selection overlay was toggled", () => chatOverlay.SelectionOverlayState == Visibility.Visible);
|
||||
AddAssert("Chat overlay was shown", () => chatOverlay.State.Value == Visibility.Visible);
|
||||
AddStep("Close chat overlay", () => chatOverlay.Hide());
|
||||
AddAssert("Channel selection overlay was hidden", () => chatOverlay.SelectionOverlayState == Visibility.Hidden);
|
||||
AddAssert("Chat overlay was hidden", () => chatOverlay.State.Value == Visibility.Hidden);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestToggleChatWithChannelJoined()
|
||||
{
|
||||
AddStep("Join channel 1", () => channelManager.JoinChannel(channel1));
|
||||
AddStep("Toggle chat overlay", () => chatOverlay.Show());
|
||||
AddAssert("Channel selection overlay was not toggled", () => chatOverlay.SelectionOverlayState == Visibility.Hidden);
|
||||
AddAssert("Chat overlay was shown", () => chatOverlay.State.Value == Visibility.Visible);
|
||||
AddStep("Close chat overlay", () => chatOverlay.Hide());
|
||||
AddAssert("Channel selection overlay was hidden", () => chatOverlay.SelectionOverlayState == Visibility.Hidden);
|
||||
AddAssert("Chat overlay was hidden", () => chatOverlay.State.Value == Visibility.Hidden);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When a channel is joined and no previous channels are joined, the channel that was joined will be selected.
|
||||
/// Channel selector closes when a new channel is selected. This is blocked for this scenario.
|
||||
/// This test expects that the channel selection overlay remains open for this reason.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestJoinChannelWhileOpen()
|
||||
{
|
||||
AddStep("Toggle chat overlay", () => chatOverlay.Show());
|
||||
AddStep("Join channel 1", () => channelManager.JoinChannel(channel1));
|
||||
AddAssert("Current channel is channel 1", () => channelManager.CurrentChannel.Value == channel1);
|
||||
AddAssert("Channel selection overlay remained open", () => chatOverlay.SelectionOverlayState == Visibility.Visible);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTabbingAwayClosesSelector()
|
||||
{
|
||||
AddStep("Toggle chat overlay", () => chatOverlay.Show());
|
||||
AddStep("Join channel 1", () => channelManager.JoinChannel(channel1));
|
||||
AddStep("Join channel 2", () => channelManager.JoinChannel(channel2));
|
||||
|
||||
// There is currently no way to map a tab drawable to its respective value at this level, so this test relies on the tab's location in AvailableTabs
|
||||
AddStep("Switch to channel 2", () => clickDrawable(chatOverlay.AvailableTabs.First()));
|
||||
AddAssert("Current channel is channel 2", () => channelManager.CurrentChannel.Value == channel2);
|
||||
AddAssert("Channel selector was closed", () => chatOverlay.SelectionOverlayState == Visibility.Hidden);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the current channel is closed, the next available channel will be selected.
|
||||
/// Channel selector closes when a new channel is selected. This is blocked for this scenario.
|
||||
/// This test expects that the channel selection overlay remains open for this reason.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCloseChannelWhileSelectorOpen()
|
||||
{
|
||||
AddStep("Toggle chat overlay", () => chatOverlay.Show());
|
||||
AddStep("Join channel 1", () => channelManager.JoinChannel(channel1));
|
||||
AddStep("Join channel 2", () => channelManager.JoinChannel(channel2));
|
||||
AddAssert("Current channel is channel 1", () => channelManager.CurrentChannel.Value == channel1);
|
||||
AddStep("Close channel 1", () => clickDrawable(chatOverlay.AvailableTabs.Last().CloseButton.Child));
|
||||
AddAssert("Current channel is channel 2", () => channelManager.CurrentChannel.Value == channel2);
|
||||
AddAssert("Channel selection overlay remained open", () => chatOverlay.SelectionOverlayState == Visibility.Visible);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCloseChannelWhileSelectorClosed()
|
||||
{
|
||||
AddStep("Toggle chat overlay", () => chatOverlay.Show());
|
||||
AddStep("Join channel 1", () => channelManager.JoinChannel(channel1));
|
||||
AddStep("Join channel 2", () => channelManager.JoinChannel(channel2));
|
||||
AddStep("Switch to channel 2", () => clickDrawable(chatOverlay.AvailableTabs.First()));
|
||||
AddStep("Close channel 2", () => clickDrawable(chatOverlay.AvailableTabs.First().CloseButton.Child));
|
||||
AddAssert("Selector remained closed", () => chatOverlay.SelectionOverlayState == Visibility.Hidden);
|
||||
AddAssert("Current channel is channel 2", () => channelManager.CurrentChannel.Value == channel1);
|
||||
AddStep("Close channel 1", () => clickDrawable(chatOverlay.AvailableTabs.First().CloseButton.Child));
|
||||
AddAssert("Channel selection overlay was toggled", () => chatOverlay.SelectionOverlayState == Visibility.Visible);
|
||||
}
|
||||
|
||||
private void clickDrawable(Drawable d)
|
||||
{
|
||||
InputManager.MoveMouseTo(d);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
}
|
||||
|
||||
private class TestChatOverlay : ChatOverlay
|
||||
{
|
||||
public Visibility SelectionOverlayState => ChannelSelectionOverlay.State.Value;
|
||||
|
||||
protected override ChannelTabControl CreateChannelTabControl() => new TestTabControl();
|
||||
|
||||
public IEnumerable<TestChannelTabItem> AvailableTabs => ((TestTabControl)ChannelTabControl).AvailableTabs();
|
||||
}
|
||||
|
||||
private class TestTabControl : ChannelTabControl
|
||||
{
|
||||
protected override TabItem<Channel> CreateTabItem(Channel value) => new TestChannelTabItem(value) { OnRequestClose = TabCloseRequested };
|
||||
|
||||
public IEnumerable<TestChannelTabItem> AvailableTabs()
|
||||
{
|
||||
foreach (var tab in TabContainer)
|
||||
{
|
||||
if (!(tab is ChannelSelectorTabItem))
|
||||
yield return (TestChannelTabItem)tab;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class TestChannelTabItem : PrivateChannelTabItem
|
||||
{
|
||||
public TestChannelTabItem(Channel channel)
|
||||
: base(channel)
|
||||
{
|
||||
}
|
||||
|
||||
public new ClickableContainer CloseButton => base.CloseButton;
|
||||
}
|
||||
}
|
||||
}
|
@ -57,10 +57,10 @@ namespace osu.Game.Overlays.Chat.Tabs
|
||||
switch (value.Type)
|
||||
{
|
||||
default:
|
||||
return new ChannelTabItem(value) { OnRequestClose = tabCloseRequested };
|
||||
return new ChannelTabItem(value) { OnRequestClose = TabCloseRequested };
|
||||
|
||||
case ChannelType.PM:
|
||||
return new PrivateChannelTabItem(value) { OnRequestClose = tabCloseRequested };
|
||||
return new PrivateChannelTabItem(value) { OnRequestClose = TabCloseRequested };
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ namespace osu.Game.Overlays.Chat.Tabs
|
||||
selectorTab.Active.Value = false;
|
||||
}
|
||||
|
||||
private void tabCloseRequested(TabItem<Channel> tab)
|
||||
protected void TabCloseRequested(TabItem<Channel> tab)
|
||||
{
|
||||
int totalTabs = TabContainer.Count - 1; // account for selectorTab
|
||||
int currentIndex = MathHelper.Clamp(TabContainer.IndexOf(tab), 1, totalTabs);
|
||||
|
@ -45,7 +45,9 @@ namespace osu.Game.Overlays
|
||||
|
||||
public const float TAB_AREA_HEIGHT = 50;
|
||||
|
||||
private ChannelTabControl channelTabControl;
|
||||
protected ChannelTabControl ChannelTabControl;
|
||||
|
||||
protected virtual ChannelTabControl CreateChannelTabControl() => new ChannelTabControl();
|
||||
|
||||
private Container chatContainer;
|
||||
private TabsArea tabsArea;
|
||||
@ -55,9 +57,10 @@ namespace osu.Game.Overlays
|
||||
public Bindable<double> ChatHeight { get; set; }
|
||||
|
||||
private Container channelSelectionContainer;
|
||||
private ChannelSelectionOverlay channelSelectionOverlay;
|
||||
protected ChannelSelectionOverlay ChannelSelectionOverlay;
|
||||
|
||||
public override bool Contains(Vector2 screenSpacePos) => chatContainer.ReceivePositionalInputAt(screenSpacePos) || (channelSelectionOverlay.State.Value == Visibility.Visible && channelSelectionOverlay.ReceivePositionalInputAt(screenSpacePos));
|
||||
public override bool Contains(Vector2 screenSpacePos) => chatContainer.ReceivePositionalInputAt(screenSpacePos)
|
||||
|| (ChannelSelectionOverlay.State.Value == Visibility.Visible && ChannelSelectionOverlay.ReceivePositionalInputAt(screenSpacePos));
|
||||
|
||||
public ChatOverlay()
|
||||
{
|
||||
@ -81,7 +84,7 @@ namespace osu.Game.Overlays
|
||||
Masking = true,
|
||||
Children = new[]
|
||||
{
|
||||
channelSelectionOverlay = new ChannelSelectionOverlay
|
||||
ChannelSelectionOverlay = new ChannelSelectionOverlay
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
@ -154,31 +157,26 @@ namespace osu.Game.Overlays
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
},
|
||||
channelTabControl = new ChannelTabControl
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
OnRequestLeave = channelManager.LeaveChannel
|
||||
},
|
||||
ChannelTabControl = CreateChannelTabControl().With(d =>
|
||||
{
|
||||
d.Anchor = Anchor.BottomLeft;
|
||||
d.Origin = Anchor.BottomLeft;
|
||||
d.RelativeSizeAxes = Axes.Both;
|
||||
d.OnRequestLeave = channelManager.LeaveChannel;
|
||||
}
|
||||
),
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
channelTabControl.Current.ValueChanged += current => channelManager.CurrentChannel.Value = current.NewValue;
|
||||
channelTabControl.ChannelSelectorActive.ValueChanged += active => channelSelectionOverlay.State.Value = active.NewValue ? Visibility.Visible : Visibility.Hidden;
|
||||
channelSelectionOverlay.State.ValueChanged += state =>
|
||||
ChannelTabControl.Current.ValueChanged += current => channelManager.CurrentChannel.Value = current.NewValue;
|
||||
ChannelTabControl.ChannelSelectorActive.ValueChanged += active => ChannelSelectionOverlay.State.Value = active.NewValue ? Visibility.Visible : Visibility.Hidden;
|
||||
ChannelSelectionOverlay.State.ValueChanged += state =>
|
||||
{
|
||||
if (state.NewValue == Visibility.Hidden && channelManager.JoinedChannels.Count == 0)
|
||||
{
|
||||
channelSelectionOverlay.Show();
|
||||
Hide();
|
||||
return;
|
||||
}
|
||||
|
||||
channelTabControl.ChannelSelectorActive.Value = state.NewValue == Visibility.Visible;
|
||||
// Propagate the visibility state to ChannelSelectorActive
|
||||
ChannelTabControl.ChannelSelectorActive.Value = state.NewValue == Visibility.Visible;
|
||||
|
||||
if (state.NewValue == Visibility.Visible)
|
||||
{
|
||||
@ -190,8 +188,8 @@ namespace osu.Game.Overlays
|
||||
textbox.HoldFocus = true;
|
||||
};
|
||||
|
||||
channelSelectionOverlay.OnRequestJoin = channel => channelManager.JoinChannel(channel);
|
||||
channelSelectionOverlay.OnRequestLeave = channelManager.LeaveChannel;
|
||||
ChannelSelectionOverlay.OnRequestJoin = channel => channelManager.JoinChannel(channel);
|
||||
ChannelSelectionOverlay.OnRequestLeave = channelManager.LeaveChannel;
|
||||
|
||||
ChatHeight = config.GetBindable<double>(OsuSetting.ChatDisplayHeight);
|
||||
ChatHeight.ValueChanged += height =>
|
||||
@ -217,11 +215,11 @@ namespace osu.Game.Overlays
|
||||
channelManager.JoinedChannels.ItemsAdded += onChannelAddedToJoinedChannels;
|
||||
channelManager.JoinedChannels.ItemsRemoved += onChannelRemovedFromJoinedChannels;
|
||||
foreach (Channel channel in channelManager.JoinedChannels)
|
||||
channelTabControl.AddChannel(channel);
|
||||
ChannelTabControl.AddChannel(channel);
|
||||
|
||||
channelManager.AvailableChannels.ItemsAdded += availableChannelsChanged;
|
||||
channelManager.AvailableChannels.ItemsRemoved += availableChannelsChanged;
|
||||
channelSelectionOverlay.UpdateAvailableChannels(channelManager.AvailableChannels);
|
||||
ChannelSelectionOverlay.UpdateAvailableChannels(channelManager.AvailableChannels);
|
||||
|
||||
currentChannel = channelManager.CurrentChannel.GetBoundCopy();
|
||||
currentChannel.BindValueChanged(currentChannelChanged, true);
|
||||
@ -236,7 +234,7 @@ namespace osu.Game.Overlays
|
||||
{
|
||||
textbox.Current.Disabled = true;
|
||||
currentChannelContainer.Clear(false);
|
||||
channelSelectionOverlay.Show();
|
||||
ChannelSelectionOverlay.Show();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -245,8 +243,8 @@ namespace osu.Game.Overlays
|
||||
|
||||
textbox.Current.Disabled = e.NewValue.ReadOnly;
|
||||
|
||||
if (channelTabControl.Current.Value != e.NewValue)
|
||||
Scheduler.Add(() => channelTabControl.Current.Value = e.NewValue);
|
||||
if (ChannelTabControl.Current.Value != e.NewValue)
|
||||
Scheduler.Add(() => ChannelTabControl.Current.Value = e.NewValue);
|
||||
|
||||
var loaded = loadedChannels.Find(d => d.Channel == e.NewValue);
|
||||
|
||||
@ -294,7 +292,7 @@ namespace osu.Game.Overlays
|
||||
double targetChatHeight = startDragChatHeight - (e.MousePosition.Y - e.MouseDownPosition.Y) / Parent.DrawSize.Y;
|
||||
|
||||
// If the channel selection screen is shown, mind its minimum height
|
||||
if (channelSelectionOverlay.State.Value == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height)
|
||||
if (ChannelSelectionOverlay.State.Value == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height)
|
||||
targetChatHeight = 1f - channel_selection_min_height;
|
||||
|
||||
ChatHeight.Value = targetChatHeight;
|
||||
@ -311,9 +309,9 @@ namespace osu.Game.Overlays
|
||||
|
||||
private void selectTab(int index)
|
||||
{
|
||||
var channel = channelTabControl.Items.Skip(index).FirstOrDefault();
|
||||
var channel = ChannelTabControl.Items.Skip(index).FirstOrDefault();
|
||||
if (channel != null && !(channel is ChannelSelectorTabItem.ChannelSelectorTabChannel))
|
||||
channelTabControl.Current.Value = channel;
|
||||
ChannelTabControl.Current.Value = channel;
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(KeyDownEvent e)
|
||||
@ -358,6 +356,10 @@ namespace osu.Game.Overlays
|
||||
this.FadeIn(transition_length, Easing.OutQuint);
|
||||
|
||||
textbox.HoldFocus = true;
|
||||
|
||||
if (channelManager.CurrentChannel.Value == null || channelManager.CurrentChannel.Value is ChannelSelectorTabItem.ChannelSelectorTabChannel)
|
||||
ChannelSelectionOverlay.Show();
|
||||
|
||||
base.PopIn();
|
||||
}
|
||||
|
||||
@ -366,7 +368,7 @@ namespace osu.Game.Overlays
|
||||
this.MoveToY(Height, transition_length, Easing.InSine);
|
||||
this.FadeOut(transition_length, Easing.InSine);
|
||||
|
||||
channelSelectionOverlay.Hide();
|
||||
ChannelSelectionOverlay.Hide();
|
||||
|
||||
textbox.HoldFocus = false;
|
||||
base.PopOut();
|
||||
@ -375,20 +377,20 @@ namespace osu.Game.Overlays
|
||||
private void onChannelAddedToJoinedChannels(IEnumerable<Channel> channels)
|
||||
{
|
||||
foreach (Channel channel in channels)
|
||||
channelTabControl.AddChannel(channel);
|
||||
ChannelTabControl.AddChannel(channel);
|
||||
}
|
||||
|
||||
private void onChannelRemovedFromJoinedChannels(IEnumerable<Channel> channels)
|
||||
{
|
||||
foreach (Channel channel in channels)
|
||||
{
|
||||
channelTabControl.RemoveChannel(channel);
|
||||
ChannelTabControl.RemoveChannel(channel);
|
||||
loadedChannels.Remove(loadedChannels.Find(c => c.Channel == channel));
|
||||
}
|
||||
}
|
||||
|
||||
private void availableChannelsChanged(IEnumerable<Channel> channels)
|
||||
=> channelSelectionOverlay.UpdateAvailableChannels(channelManager.AvailableChannels);
|
||||
=> ChannelSelectionOverlay.UpdateAvailableChannels(channelManager.AvailableChannels);
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user