From 2122966cd41a4435496f3e525a2e2aa9b5682394 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 20:56:33 +0900 Subject: [PATCH 1/3] Show channel selector when no channels are joined --- .../Overlays/Chat/Tabs/ChannelTabControl.cs | 5 ++-- osu.Game/Overlays/ChatOverlay.cs | 28 ++++++++++++------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index 79cb0a4d14..dc72c8053a 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -94,13 +94,12 @@ namespace osu.Game.Overlays.Chat.Tabs { if (tab is ChannelSelectorTabItem) { - tab.Active.Toggle(); + tab.Active.Value = true; return; } - selectorTab.Active.Value = false; - base.SelectTab(tab); + selectorTab.Active.Value = false; } private void tabCloseRequested(TabItem tab) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index bdb28d1246..75e22f85d1 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -52,9 +52,9 @@ namespace osu.Game.Overlays public Bindable ChatHeight { get; set; } private readonly Container channelSelectionContainer; - private readonly ChannelSelectionOverlay channelSelection; + private readonly ChannelSelectionOverlay channelSelectionOverlay; - public override bool Contains(Vector2 screenSpacePos) => chatContainer.ReceivePositionalInputAt(screenSpacePos) || channelSelection.State == Visibility.Visible && channelSelection.ReceivePositionalInputAt(screenSpacePos); + public override bool Contains(Vector2 screenSpacePos) => chatContainer.ReceivePositionalInputAt(screenSpacePos) || channelSelectionOverlay.State == Visibility.Visible && channelSelectionOverlay.ReceivePositionalInputAt(screenSpacePos); public ChatOverlay() { @@ -74,7 +74,7 @@ namespace osu.Game.Overlays Masking = true, Children = new[] { - channelSelection = new ChannelSelectionOverlay + channelSelectionOverlay = new ChannelSelectionOverlay { RelativeSizeAxes = Axes.Both, }, @@ -161,9 +161,16 @@ namespace osu.Game.Overlays }; channelTabControl.Current.ValueChanged += chat => channelManager.CurrentChannel.Value = chat; - channelTabControl.ChannelSelectorActive.ValueChanged += value => channelSelection.State = value ? Visibility.Visible : Visibility.Hidden; - channelSelection.StateChanged += state => + channelTabControl.ChannelSelectorActive.ValueChanged += value => channelSelectionOverlay.State = value ? Visibility.Visible : Visibility.Hidden; + channelSelectionOverlay.StateChanged += state => { + if (state == Visibility.Hidden && channelManager.CurrentChannel.Value == null) + { + channelSelectionOverlay.State = Visibility.Visible; + State = Visibility.Hidden; + return; + } + channelTabControl.ChannelSelectorActive.Value = state == Visibility.Visible; if (state == Visibility.Visible) @@ -176,8 +183,8 @@ namespace osu.Game.Overlays textbox.HoldFocus = true; }; - channelSelection.OnRequestJoin = channel => channelManager.JoinChannel(channel); - channelSelection.OnRequestLeave = channel => channelManager.LeaveChannel(channel); + channelSelectionOverlay.OnRequestJoin = channel => channelManager.JoinChannel(channel); + channelSelectionOverlay.OnRequestLeave = channel => channelManager.LeaveChannel(channel); } private void currentChannelChanged(Channel channel) @@ -186,6 +193,7 @@ namespace osu.Game.Overlays { textbox.Current.Disabled = true; currentChannelContainer.Clear(false); + channelSelectionOverlay.State = Visibility.Visible; return; } @@ -239,7 +247,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 (channelSelection.State == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height) + if (channelSelectionOverlay.State == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height) targetChatHeight = 1f - channel_selection_min_height; ChatHeight.Value = targetChatHeight; @@ -305,7 +313,7 @@ namespace osu.Game.Overlays channelManager.AvailableChannels.ItemsRemoved += availableChannelsChanged; //for the case that channelmanager was faster at fetching the channels than our attachment to CollectionChanged. - channelSelection.UpdateAvailableChannels(channelManager.AvailableChannels); + channelSelectionOverlay.UpdateAvailableChannels(channelManager.AvailableChannels); foreach (Channel channel in channelManager.JoinedChannels) channelTabControl.AddChannel(channel); } @@ -326,7 +334,7 @@ namespace osu.Game.Overlays } private void availableChannelsChanged(IEnumerable channels) - => channelSelection.UpdateAvailableChannels(channelManager.AvailableChannels); + => channelSelectionOverlay.UpdateAvailableChannels(channelManager.AvailableChannels); protected override void Dispose(bool isDisposing) { From 2f9de149dd28dd7980ce22afe565fa860629e926 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Dec 2018 13:56:21 +0900 Subject: [PATCH 2/3] Add constructor to create a PM channel from a User --- osu.Game/Online/Chat/Channel.cs | 11 +++++++++++ osu.Game/Online/Chat/ChannelManager.cs | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 9d3b7b5cc9..9dc357c403 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -88,6 +88,17 @@ namespace osu.Game.Online.Chat { } + /// + /// Create a private messaging channel with the specified user. + /// + /// The user to create the private conversation with. + public Channel(User user) + { + Type = ChannelType.PM; + Users.Add(user); + Name = user.Username; + } + /// /// Adds the argument message as a local echo. When this local echo is resolved will get called. /// diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 29f971078b..863ad3042f 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -79,7 +79,7 @@ namespace osu.Game.Online.Chat throw new ArgumentNullException(nameof(user)); CurrentChannel.Value = JoinedChannels.FirstOrDefault(c => c.Type == ChannelType.PM && c.Users.Count == 1 && c.Users.Any(u => u.Id == user.Id)) - ?? new Channel { Name = user.Username, Users = { user }, Type = ChannelType.PM }; + ?? new Channel(user); } private void currentChannelChanged(Channel channel) => JoinChannel(channel); From d42c45c87ea3befb2ec5c9c1d4301b2f13cd077d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Dec 2018 14:00:16 +0900 Subject: [PATCH 3/3] Add full tests --- .../Visual/TestCaseChannelTabControl.cs | 65 +++++++++---------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseChannelTabControl.cs b/osu.Game.Tests/Visual/TestCaseChannelTabControl.cs index 447337bef0..1127402adb 100644 --- a/osu.Game.Tests/Visual/TestCaseChannelTabControl.cs +++ b/osu.Game.Tests/Visual/TestCaseChannelTabControl.cs @@ -4,15 +4,12 @@ using System; using System.Collections.Generic; using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Online.Chat; using osu.Game.Overlays.Chat.Tabs; using osu.Game.Users; @@ -74,50 +71,50 @@ namespace osu.Game.Tests.Visual channelTabControl.OnRequestLeave += channel => channelTabControl.RemoveChannel(channel); channelTabControl.Current.ValueChanged += channel => currentText.Text = "Currently selected channel: " + channel.ToString(); - AddStep("Add random private channel", addRandomUser); + AddStep("Add random private channel", addRandomPrivateChannel); AddAssert("There is only one channels", () => channelTabControl.Items.Count() == 2); - AddRepeatStep("Add 3 random private channels", addRandomUser, 3); + AddRepeatStep("Add 3 random private channels", addRandomPrivateChannel, 3); AddAssert("There are four channels", () => channelTabControl.Items.Count() == 5); AddStep("Add random public channel", () => addChannel(RNG.Next().ToString())); - AddRepeatStep("Select a random channel", () => channelTabControl.Current.Value = channelTabControl.Items.ElementAt(RNG.Next(channelTabControl.Items.Count())), 20); - } + AddRepeatStep("Select a random channel", () => channelTabControl.Current.Value = channelTabControl.Items.ElementAt(RNG.Next(channelTabControl.Items.Count() - 1)), 20); - private List users; + Channel channelBefore = channelTabControl.Items.First(); + AddStep("set first channel", () => channelTabControl.Current.Value = channelBefore); - private void addRandomUser() - { - channelTabControl.AddChannel(new Channel + AddStep("select selector tab", () => channelTabControl.Current.Value = channelTabControl.Items.Last()); + AddAssert("selector tab is active", () => channelTabControl.ChannelSelectorActive.Value); + + AddAssert("check channel unchanged", () => channelBefore == channelTabControl.Current.Value); + + AddStep("set second channel", () => channelTabControl.Current.Value = channelTabControl.Items.Skip(1).First()); + AddAssert("selector tab is inactive", () => !channelTabControl.ChannelSelectorActive.Value); + + AddUntilStep(() => { - Users = - { - users?.Count > 0 - ? users[RNG.Next(0, users.Count - 1)] - : new User - { - Id = RNG.Next(), - Username = "testuser" + RNG.Next(1000) - } - } - }); + var first = channelTabControl.Items.First(); + if (first.Name == "+") + return true; + + channelTabControl.RemoveChannel(first); + return false; + }, "remove all channels"); + + AddAssert("selector tab is active", () => channelTabControl.ChannelSelectorActive.Value); } - private void addChannel(string name) - { + private void addRandomPrivateChannel() => + channelTabControl.AddChannel(new Channel(new User + { + Id = RNG.Next(1000, 10000000), + Username = "Test User " + RNG.Next(1000) + })); + + private void addChannel(string name) => channelTabControl.AddChannel(new Channel { Type = ChannelType.Public, Name = name }); - } - - [BackgroundDependencyLoader] - private void load(IAPIProvider api) - { - GetUsersRequest req = new GetUsersRequest(); - req.Success += list => users = list.Select(e => e.User).ToList(); - - api.Queue(req); - } } }