From b4c68f4cf7b07930191e9ced016b52a180d59ffc Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Mon, 22 Oct 2018 23:16:57 +0300 Subject: [PATCH 01/20] Show a warning prior to opening external links --- osu.Game.Tests/Visual/TestCaseChatLink.cs | 3 ++ .../Graphics/Containers/LinkFlowContainer.cs | 7 ++-- osu.Game/Overlays/Chat/ExternalLinkDialog.cs | 32 +++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Overlays/Chat/ExternalLinkDialog.cs diff --git a/osu.Game.Tests/Visual/TestCaseChatLink.cs b/osu.Game.Tests/Visual/TestCaseChatLink.cs index 12a7ee9c12..6240062aab 100644 --- a/osu.Game.Tests/Visual/TestCaseChatLink.cs +++ b/osu.Game.Tests/Visual/TestCaseChatLink.cs @@ -23,6 +23,7 @@ namespace osu.Game.Tests.Visual public class TestCaseChatLink : OsuTestCase { private readonly TestChatLineContainer textContainer; + private readonly DialogOverlay dialogOverlay; private Color4 linkColour; public override IReadOnlyList RequiredTypes => new[] @@ -37,6 +38,7 @@ namespace osu.Game.Tests.Visual public TestCaseChatLink() { + Add(dialogOverlay = new DialogOverlay { Depth = float.MinValue }); Add(textContainer = new TestChatLineContainer { Padding = new MarginPadding { Left = 20, Right = 20 }, @@ -50,6 +52,7 @@ namespace osu.Game.Tests.Visual private void load(OsuColour colours) { linkColour = colours.Blue; + Dependencies.Cache(dialogOverlay); Dependencies.Cache(new ChatOverlay { AvailableChannels = diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index e4e7828d0e..11dd1925be 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Sprites; using System.Collections.Generic; using osu.Framework.Platform; using osu.Game.Overlays; +using osu.Game.Overlays.Chat; using osu.Game.Overlays.Notifications; namespace osu.Game.Graphics.Containers @@ -24,13 +25,15 @@ namespace osu.Game.Graphics.Containers private Action showNotImplementedError; private GameHost host; + private DialogOverlay dialogOverlay; [BackgroundDependencyLoader(true)] - private void load(OsuGame game, NotificationOverlay notifications, GameHost host) + private void load(OsuGame game, NotificationOverlay notifications, GameHost host, DialogOverlay dialogOverlay) { // will be null in tests this.game = game; this.host = host; + this.dialogOverlay = dialogOverlay; showNotImplementedError = () => notifications?.Post(new SimpleNotification { @@ -88,7 +91,7 @@ namespace osu.Game.Graphics.Containers showNotImplementedError?.Invoke(); break; case LinkAction.External: - host.OpenUrlExternally(url); + dialogOverlay.Push(new ExternalLinkDialog(url, () => host.OpenUrlExternally(url))); break; case LinkAction.OpenUserProfile: if (long.TryParse(linkArgument, out long userId)) diff --git a/osu.Game/Overlays/Chat/ExternalLinkDialog.cs b/osu.Game/Overlays/Chat/ExternalLinkDialog.cs new file mode 100644 index 0000000000..51073f77ca --- /dev/null +++ b/osu.Game/Overlays/Chat/ExternalLinkDialog.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Game.Graphics; +using osu.Game.Overlays.Dialog; + +namespace osu.Game.Overlays.Chat +{ + public class ExternalLinkDialog : PopupDialog + { + public ExternalLinkDialog(string url, Action openExternalLinkAction) + { + BodyText = url; + + Icon = FontAwesome.fa_warning; + HeaderText = "Confirm opening external link"; + Buttons = new PopupDialogButton[] + { + new PopupDialogOkButton + { + Text = @"Yes. Go for it.", + Action = openExternalLinkAction + }, + new PopupDialogCancelButton + { + Text = @"No! Abort mission!" + }, + }; + } + } +} From 805f8d98c4ab7594193733ba8203a35e484d46bd Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Mon, 22 Oct 2018 23:57:37 +0300 Subject: [PATCH 02/20] Implement warn about opening external links option --- osu.Game/Configuration/OsuConfigManager.cs | 5 +++- .../Graphics/Containers/LinkFlowContainer.cs | 14 ++++++++-- .../Settings/Sections/Online/WebSettings.cs | 27 +++++++++++++++++++ .../Settings/Sections/OnlineSection.cs | 2 ++ 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 9ac2cabe9f..8d451a92e4 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -42,6 +42,8 @@ namespace osu.Game.Configuration if (!val) Set(OsuSetting.SavePassword, false); }; + Set(OsuSetting.WarnAboutOpeningExternalLink, true); + // Audio Set(OsuSetting.VolumeInactive, 0.25, 0, 1, 0.01); @@ -148,6 +150,7 @@ namespace osu.Game.Configuration BeatmapSkins, BeatmapHitsounds, IncreaseFirstObjectVisibility, - ScoreDisplayMode + ScoreDisplayMode, + WarnAboutOpeningExternalLink } } diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 11dd1925be..fd1aeae80a 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -7,7 +7,9 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using System.Collections.Generic; +using osu.Framework.Configuration; using osu.Framework.Platform; +using osu.Game.Configuration; using osu.Game.Overlays; using osu.Game.Overlays.Chat; using osu.Game.Overlays.Notifications; @@ -25,16 +27,20 @@ namespace osu.Game.Graphics.Containers private Action showNotImplementedError; private GameHost host; + private DialogOverlay dialogOverlay; + private Bindable warnAboutOpeningExternal; [BackgroundDependencyLoader(true)] - private void load(OsuGame game, NotificationOverlay notifications, GameHost host, DialogOverlay dialogOverlay) + private void load(OsuGame game, NotificationOverlay notifications, GameHost host, DialogOverlay dialogOverlay, OsuConfigManager config) { // will be null in tests this.game = game; this.host = host; this.dialogOverlay = dialogOverlay; + warnAboutOpeningExternal = config.GetBindable(OsuSetting.WarnAboutOpeningExternalLink); + showNotImplementedError = () => notifications?.Post(new SimpleNotification { Text = @"This link type is not yet supported!", @@ -91,7 +97,11 @@ namespace osu.Game.Graphics.Containers showNotImplementedError?.Invoke(); break; case LinkAction.External: - dialogOverlay.Push(new ExternalLinkDialog(url, () => host.OpenUrlExternally(url))); + void externalAction() => host.OpenUrlExternally(url); + if (warnAboutOpeningExternal) + dialogOverlay.Push(new ExternalLinkDialog(url, externalAction)); + else + externalAction(); break; case LinkAction.OpenUserProfile: if (long.TryParse(linkArgument, out long userId)) diff --git a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs new file mode 100644 index 0000000000..e2a7aef2d7 --- /dev/null +++ b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs @@ -0,0 +1,27 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Configuration; + +namespace osu.Game.Overlays.Settings.Sections.Online +{ + public class WebSettings : SettingsSubsection + { + protected override string Header => "Web"; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + Children = new Drawable[] + { + new SettingsCheckbox + { + LabelText = "Warn about opening external links", + Bindable = config.GetBindable(OsuSetting.WarnAboutOpeningExternalLink) + }, + }; + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs index 28cb503288..3a2e52d2eb 100644 --- a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs +++ b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Game.Graphics; +using osu.Game.Overlays.Settings.Sections.Online; namespace osu.Game.Overlays.Settings.Sections { @@ -15,6 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections { Children = new Drawable[] { + new WebSettings() }; } } From 7401fabb5dc62c83df218d0e17c998601018d5c0 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Tue, 23 Oct 2018 23:03:00 +0300 Subject: [PATCH 03/20] Extract external link opening to the ExternalLinkOpener class --- .../Graphics/Containers/LinkFlowContainer.cs | 20 +--------- osu.Game/Online/Chat/ExternalLinkOpener.cs | 38 +++++++++++++++++++ osu.Game/OsuGame.cs | 6 +++ 3 files changed, 46 insertions(+), 18 deletions(-) create mode 100644 osu.Game/Online/Chat/ExternalLinkOpener.cs diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index fd1aeae80a..c3d58e940e 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -7,11 +7,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using System.Collections.Generic; -using osu.Framework.Configuration; -using osu.Framework.Platform; -using osu.Game.Configuration; using osu.Game.Overlays; -using osu.Game.Overlays.Chat; using osu.Game.Overlays.Notifications; namespace osu.Game.Graphics.Containers @@ -26,20 +22,12 @@ namespace osu.Game.Graphics.Containers private OsuGame game; private Action showNotImplementedError; - private GameHost host; - - private DialogOverlay dialogOverlay; - private Bindable warnAboutOpeningExternal; [BackgroundDependencyLoader(true)] - private void load(OsuGame game, NotificationOverlay notifications, GameHost host, DialogOverlay dialogOverlay, OsuConfigManager config) + private void load(OsuGame game, NotificationOverlay notifications) { // will be null in tests this.game = game; - this.host = host; - this.dialogOverlay = dialogOverlay; - - warnAboutOpeningExternal = config.GetBindable(OsuSetting.WarnAboutOpeningExternalLink); showNotImplementedError = () => notifications?.Post(new SimpleNotification { @@ -97,11 +85,7 @@ namespace osu.Game.Graphics.Containers showNotImplementedError?.Invoke(); break; case LinkAction.External: - void externalAction() => host.OpenUrlExternally(url); - if (warnAboutOpeningExternal) - dialogOverlay.Push(new ExternalLinkDialog(url, externalAction)); - else - externalAction(); + game?.OpenUrlExternally(url); break; case LinkAction.OpenUserProfile: if (long.TryParse(linkArgument, out long userId)) diff --git a/osu.Game/Online/Chat/ExternalLinkOpener.cs b/osu.Game/Online/Chat/ExternalLinkOpener.cs new file mode 100644 index 0000000000..887a168188 --- /dev/null +++ b/osu.Game/Online/Chat/ExternalLinkOpener.cs @@ -0,0 +1,38 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Platform; +using osu.Game.Configuration; +using osu.Game.Overlays; +using osu.Game.Overlays.Chat; + +namespace osu.Game.Online.Chat +{ + public class ExternalLinkOpener : Component + { + private GameHost host; + private DialogOverlay dialogOverlay; + private Bindable warnAboutOpeningExternal; + + [BackgroundDependencyLoader(true)] + private void load(GameHost host, DialogOverlay dialogOverlay, OsuConfigManager config) + { + this.host = host; + this.dialogOverlay = dialogOverlay; + warnAboutOpeningExternal = config.GetBindable(OsuSetting.WarnAboutOpeningExternalLink); + } + + public void OpenUrlExternally(string url) + { + void externalAction() => host.OpenUrlExternally(url); + + if (warnAboutOpeningExternal) + dialogOverlay.Push(new ExternalLinkDialog(url, externalAction)); + else + externalAction(); + } + } +} diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b75a37e9df..e2f20de5c6 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -31,6 +31,7 @@ using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; using osu.Game.Screens.Play; using osu.Game.Input.Bindings; +using osu.Game.Online.Chat; using osu.Game.Rulesets.Mods; using osu.Game.Skinning; using OpenTK.Graphics; @@ -103,6 +104,9 @@ namespace osu.Game private readonly List overlays = new List(); + private ExternalLinkOpener externalLinkOpener; + public void OpenUrlExternally(string url) => externalLinkOpener.OpenUrlExternally(url); + // todo: move this to SongSelect once Screen has the ability to unsuspend. [Cached] [Cached(Type = typeof(IBindable>))] @@ -383,6 +387,8 @@ namespace osu.Game dependencies.Cache(notifications); dependencies.Cache(dialogOverlay); + Add(externalLinkOpener = new ExternalLinkOpener()); + var singleDisplaySideOverlays = new OverlayContainer[] { settings, notifications }; overlays.AddRange(singleDisplaySideOverlays); From b4809f4417b065bc3a4ae18373342f3306ca8719 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 1 Nov 2018 23:52:07 +0300 Subject: [PATCH 04/20] External link warning code cleanup --- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- osu.Game/Online/Chat/ExternalLinkOpener.cs | 12 +++++------- osu.Game/OsuGame.cs | 6 +++--- osu.Game/Overlays/Chat/ExternalLinkDialog.cs | 2 +- .../Overlays/Settings/Sections/Online/WebSettings.cs | 2 +- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 8d451a92e4..8975ab8a0e 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -42,7 +42,7 @@ namespace osu.Game.Configuration if (!val) Set(OsuSetting.SavePassword, false); }; - Set(OsuSetting.WarnAboutOpeningExternalLink, true); + Set(OsuSetting.ExternalLinkWarning, true); // Audio Set(OsuSetting.VolumeInactive, 0.25, 0, 1, 0.01); @@ -151,6 +151,6 @@ namespace osu.Game.Configuration BeatmapHitsounds, IncreaseFirstObjectVisibility, ScoreDisplayMode, - WarnAboutOpeningExternalLink + ExternalLinkWarning } } diff --git a/osu.Game/Online/Chat/ExternalLinkOpener.cs b/osu.Game/Online/Chat/ExternalLinkOpener.cs index 887a168188..d8b8adbbad 100644 --- a/osu.Game/Online/Chat/ExternalLinkOpener.cs +++ b/osu.Game/Online/Chat/ExternalLinkOpener.cs @@ -15,24 +15,22 @@ namespace osu.Game.Online.Chat { private GameHost host; private DialogOverlay dialogOverlay; - private Bindable warnAboutOpeningExternal; + private Bindable externalLinkWarning; [BackgroundDependencyLoader(true)] private void load(GameHost host, DialogOverlay dialogOverlay, OsuConfigManager config) { this.host = host; this.dialogOverlay = dialogOverlay; - warnAboutOpeningExternal = config.GetBindable(OsuSetting.WarnAboutOpeningExternalLink); + externalLinkWarning = config.GetBindable(OsuSetting.ExternalLinkWarning); } public void OpenUrlExternally(string url) { - void externalAction() => host.OpenUrlExternally(url); - - if (warnAboutOpeningExternal) - dialogOverlay.Push(new ExternalLinkDialog(url, externalAction)); + if (externalLinkWarning) + dialogOverlay.Push(new ExternalLinkDialog(url, () => host.OpenUrlExternally(url))); else - externalAction(); + host.OpenUrlExternally(url); } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e2f20de5c6..d016cd3df0 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -104,9 +104,6 @@ namespace osu.Game private readonly List overlays = new List(); - private ExternalLinkOpener externalLinkOpener; - public void OpenUrlExternally(string url) => externalLinkOpener.OpenUrlExternally(url); - // todo: move this to SongSelect once Screen has the ability to unsuspend. [Cached] [Cached(Type = typeof(IBindable>))] @@ -182,6 +179,9 @@ namespace osu.Game LocalConfig.BindWith(OsuSetting.VolumeInactive, inactiveVolumeAdjust); } + private ExternalLinkOpener externalLinkOpener; + public void OpenUrlExternally(string url) => externalLinkOpener.OpenUrlExternally(url); + private ScheduledDelegate scoreLoad; /// diff --git a/osu.Game/Overlays/Chat/ExternalLinkDialog.cs b/osu.Game/Overlays/Chat/ExternalLinkDialog.cs index 51073f77ca..1b1212af20 100644 --- a/osu.Game/Overlays/Chat/ExternalLinkDialog.cs +++ b/osu.Game/Overlays/Chat/ExternalLinkDialog.cs @@ -14,7 +14,7 @@ namespace osu.Game.Overlays.Chat BodyText = url; Icon = FontAwesome.fa_warning; - HeaderText = "Confirm opening external link"; + HeaderText = "Are you sure you want to open the following?"; Buttons = new PopupDialogButton[] { new PopupDialogOkButton diff --git a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs index e2a7aef2d7..62e307f323 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Settings.Sections.Online new SettingsCheckbox { LabelText = "Warn about opening external links", - Bindable = config.GetBindable(OsuSetting.WarnAboutOpeningExternalLink) + Bindable = config.GetBindable(OsuSetting.ExternalLinkWarning) }, }; } From eab2776755694526f8f99c6dc1aec4718216d4b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Nov 2018 17:14:08 +0900 Subject: [PATCH 05/20] Fix a crash on leaving the selected channel --- osu.Game/Overlays/ChatOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index e45373c36f..6a5b72c0f3 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -209,7 +209,6 @@ namespace osu.Game.Overlays { textbox.Current.Disabled = true; currentChannelContainer.Clear(false); - channelTabControl.Current.Value = null; return; } From 4cde66240dcba75444ac1693aef3a117498cb122 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Nov 2018 17:14:48 +0900 Subject: [PATCH 06/20] Fix default channels not being joined --- osu.Game/Online/Chat/ChannelManager.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 9014fce18d..9ee6cfa483 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -362,12 +362,6 @@ namespace osu.Game.Online.Chat } } - if (!channelsInitialised) - { - channelsInitialised = true; - // we want this to run after the first presence so we can see if the user is in any channels already. - initializeChannels(); - } //todo: handle left channels @@ -379,6 +373,13 @@ namespace osu.Game.Online.Chat lastMessageId = updates.Messages.LastOrDefault()?.Id ?? lastMessageId; } + if (!channelsInitialised) + { + channelsInitialised = true; + // we want this to run after the first presence so we can see if the user is in any channels already. + initializeChannels(); + } + fetchUpdates(); }; From 88f82eb722738f323314afa5e51467deecd9b01a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Nov 2018 17:15:10 +0900 Subject: [PATCH 07/20] Fix instabilities in channel join logic --- osu.Game/Online/Chat/ChannelManager.cs | 89 +++++++++++++++++--------- 1 file changed, 57 insertions(+), 32 deletions(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 9ee6cfa483..621cdb5737 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -223,13 +223,11 @@ namespace osu.Game.Online.Chat { foreach (var channel in channels) { - // add as available if not already - if (AvailableChannels.All(c => c.Id != channel.Id)) - AvailableChannels.Add(channel); + var ch = getChannel(channel, addToAvailable: true); // join any channels classified as "defaults" if (joinDefaults && defaultChannels.Any(c => c.Equals(channel.Name, StringComparison.OrdinalIgnoreCase))) - JoinChannel(channel); + JoinChannel(ch); } }; req.Failure += error => @@ -262,38 +260,68 @@ namespace osu.Game.Online.Chat api.Queue(fetchInitialMsgReq); } - public void JoinChannel(Channel channel) + /// + /// Find an existing channel instance for the provided channel. Lookup is performed basd on ID. + /// The provided channel may be used if an existing instance is not found. + /// + /// A candidate channel to be used for lookup or permanently on lookup failure. + /// Whether the channel should be added to if not already. + /// Whether the channel should be added to if not already. + /// The found channel. + private Channel getChannel(Channel lookup, bool addToAvailable = false, bool addToJoined = false) { - if (channel == null) return; + Channel found = null; - // ReSharper disable once AccessToModifiedClosure - var existing = JoinedChannels.FirstOrDefault(c => c.Id == channel.Id); + var available = AvailableChannels.FirstOrDefault(c => c.Id == lookup.Id); + if (available != null) + found = available; - if (existing != null) + var joined = JoinedChannels.FirstOrDefault(c => c.Id == lookup.Id); + if (found == null && joined != null) + found = joined; + + if (found == null) { - // if we already have this channel loaded, we don't want to make a second one. - channel = existing; - } - else - { - var foundSelf = channel.Users.FirstOrDefault(u => u.Id == api.LocalUser.Value.Id); + found = lookup; + + // if we're using a channel object from the server, we want to remove ourselves from the users list. + // this is because we check the first user in the channel to display a name/icon on tabs for now. + var foundSelf = found.Users.FirstOrDefault(u => u.Id == api.LocalUser.Value.Id); if (foundSelf != null) - channel.Users.Remove(foundSelf); + found.Users.Remove(foundSelf); + } - JoinedChannels.Add(channel); + if (joined == null && addToJoined) JoinedChannels.Add(found); + if (available == null && addToAvailable) AvailableChannels.Add(found); - if (channel.Type == ChannelType.Public && !channel.Joined) + return found; + } + + /// + /// Joins a channel if it has not already been joined. + /// + /// The channel to join. + /// Whether the channel has already been joined server-side. Will skip a join request. + /// The joined channel. Note that this may not match the parameter channel as it is a backed object. + public Channel JoinChannel(Channel channel, bool alreadyJoined = false) + { + if (channel == null) return null; + + channel = getChannel(channel, addToJoined: true); + + // ensure we are joined to the channel + if (!channel.Joined.Value) + { + if (!alreadyJoined && channel.Type == ChannelType.Public) { var req = new JoinChannelRequest(channel, api.LocalUser); - req.Success += () => - { - channel.Joined.Value = true; - JoinChannel(channel); - }; + req.Success += () => JoinChannel(channel, true); req.Failure += ex => LeaveChannel(channel); api.Queue(req); - return; + return channel; } + + channel.Joined.Value = true; } if (CurrentChannel.Value == null) @@ -304,6 +332,8 @@ namespace osu.Game.Online.Chat // let's fetch a small number of messages to bring us up-to-date with the backlog. fetchInitalMessages(channel); } + + return channel; } public void LeaveChannel(Channel channel) @@ -353,13 +383,8 @@ namespace osu.Game.Online.Chat { foreach (var channel in updates.Presence) { - if (!channel.Joined.Value) - { - // we received this from the server so should mark the channel already joined. - channel.Joined.Value = true; - - JoinChannel(channel); - } + // we received this from the server so should mark the channel already joined. + JoinChannel(channel, true); } From d67792168029a6d9f2ea491d102d45aa3ce46c0d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Nov 2018 18:53:50 +0900 Subject: [PATCH 08/20] Remove excess newline --- osu.Game/Online/Chat/ChannelManager.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 621cdb5737..3ce162ee30 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -387,7 +387,6 @@ namespace osu.Game.Online.Chat JoinChannel(channel, true); } - //todo: handle left channels handleChannelMessages(updates.Messages); From b31efb7bb992256134d581b30a6b603ffbbe77fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Nov 2018 20:31:47 +0900 Subject: [PATCH 09/20] Fix PM channel type --- osu.Game/Online/Chat/ChannelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 3ce162ee30..d9098956ec 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -77,7 +77,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 } }; + ?? new Channel { Name = user.Username, Users = { user }, Type = ChannelType.PM }; } private void currentChannelChanged(Channel channel) => JoinChannel(channel); From 2126cf0d9a6f68acf52002a018396fba9cf3ec75 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Nov 2018 20:44:41 +0900 Subject: [PATCH 10/20] Fix join process for PMs being incorrect --- osu.Game/Online/Chat/ChannelManager.cs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index d9098956ec..a9610e72b1 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -312,16 +312,20 @@ namespace osu.Game.Online.Chat // ensure we are joined to the channel if (!channel.Joined.Value) { - if (!alreadyJoined && channel.Type == ChannelType.Public) + if (alreadyJoined) + channel.Joined.Value = true; + else { - var req = new JoinChannelRequest(channel, api.LocalUser); - req.Success += () => JoinChannel(channel, true); - req.Failure += ex => LeaveChannel(channel); - api.Queue(req); - return channel; + switch (channel.Type) + { + case ChannelType.Public: + var req = new JoinChannelRequest(channel, api.LocalUser); + req.Success += () => JoinChannel(channel, true); + req.Failure += ex => LeaveChannel(channel); + api.Queue(req); + return channel; + } } - - channel.Joined.Value = true; } if (CurrentChannel.Value == null) From 5caa67d73505475a3659f43fb511167530fc578b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 22 Nov 2018 12:12:34 +0900 Subject: [PATCH 11/20] Hide playlist when MusicController is hidden --- osu.Game/Overlays/MusicController.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index dfac007ed9..88cc730143 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -406,6 +406,8 @@ namespace osu.Game.Overlays { base.PopOut(); + playlist.State = Visibility.Hidden; + this.FadeOut(transition_length, Easing.OutQuint); dragContainer.ScaleTo(0.9f, transition_length, Easing.OutQuint); } From a144e975687d43bde1d36fe330f614758793104d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Nov 2018 18:27:22 +0900 Subject: [PATCH 12/20] Fix crash on creating two new PM channels --- osu.Game/Online/Chat/ChannelManager.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index a9610e72b1..73ac7c9df4 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -272,11 +272,13 @@ namespace osu.Game.Online.Chat { Channel found = null; - var available = AvailableChannels.FirstOrDefault(c => c.Id == lookup.Id); + bool lookupCondition(Channel ch) => lookup.Id > 0 ? ch.Id == lookup.Id : lookup.Name == ch.Name; + + var available = AvailableChannels.FirstOrDefault(lookupCondition); if (available != null) found = available; - var joined = JoinedChannels.FirstOrDefault(c => c.Id == lookup.Id); + var joined = JoinedChannels.FirstOrDefault(lookupCondition); if (found == null && joined != null) found = joined; From 6cd69b794d170c8a4c51e8be091166824e1ef5c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Nov 2018 19:08:46 +0900 Subject: [PATCH 13/20] Fix leaderboard accessing drawables in a possibly invalid state --- osu.Game/Screens/Select/Leaderboards/Leaderboard.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs index 4a677001a0..0748f68dca 100644 --- a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs @@ -310,9 +310,9 @@ namespace osu.Game.Screens.Select.Leaderboards currentPlaceholder = placeholder; } - protected override void Update() + protected override void UpdateAfterChildren() { - base.Update(); + base.UpdateAfterChildren(); var fadeStart = scrollContainer.Current + scrollContainer.DrawHeight; From 61fdfe39fdf665add23f714ec3729ba0734e8314 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Nov 2018 19:21:32 +0900 Subject: [PATCH 14/20] Add comment --- osu.Game/Overlays/MusicController.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 88cc730143..58e03bd0cd 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -406,6 +406,8 @@ namespace osu.Game.Overlays { base.PopOut(); + // This is here mostly as a performance fix. + // If the playlist is not hidden it will update children even when the music controller is hidden (due to AlwaysPresent). playlist.State = Visibility.Hidden; this.FadeOut(transition_length, Easing.OutQuint); From a48c26d9993696fda11d624d5508dd8f06955530 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Nov 2018 19:40:44 +0900 Subject: [PATCH 15/20] Fix precision scroll events being handled incorrectly by editor --- osu.Game/Screens/Edit/Editor.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 0be15de7f4..b355d1f349 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osuTK.Graphics; using osu.Framework.Screens; using osu.Game.Screens.Backgrounds; @@ -181,12 +182,20 @@ namespace osu.Game.Screens.Edit LoadComponentAsync(currentScreen, screenContainer.Add); } + private double scrollAccumulation; + protected override bool OnScroll(ScrollEvent e) { - if (e.ScrollDelta.X + e.ScrollDelta.Y > 0) + scrollAccumulation += e.ScrollDelta.X + e.ScrollDelta.Y * (e.IsPrecise ? 0.1 : 1); + if (Math.Abs(scrollAccumulation) < 1) + return true; + + if (scrollAccumulation > 0) clock.SeekBackward(!clock.IsRunning); else clock.SeekForward(!clock.IsRunning); + + scrollAccumulation = 0; return true; } From 10047e6815c8a72cab9c76498dc96e8f8635296b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Nov 2018 20:13:40 +0900 Subject: [PATCH 16/20] Adjust tick-based wheel control to be more correct --- osu.Game/Overlays/Volume/VolumeMeter.cs | 16 ++++++++++------ osu.Game/Screens/Edit/Editor.cs | 18 +++++++++++------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index c249651f98..c67ed5b845 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -228,15 +228,19 @@ namespace osu.Game.Overlays.Volume public void Decrease(double amount = 1, bool isPrecise = false) => adjust(-amount, isPrecise); // because volume precision is set to 0.01, this local is required to keep track of more precise adjustments and only apply when possible. - private double adjustAccumulator; + private double scrollAccumulation; private void adjust(double delta, bool isPrecise) { - adjustAccumulator += delta * adjust_step * (isPrecise ? 0.1 : 1); - if (Math.Abs(adjustAccumulator) < Bindable.Precision) - return; - Volume += adjustAccumulator; - adjustAccumulator = 0; + scrollAccumulation += delta * adjust_step * (isPrecise ? 0.1 : 1); + + var precision = Bindable.Precision; + + while (Math.Abs(scrollAccumulation) > precision) + { + Volume += Math.Sign(scrollAccumulation) * precision; + scrollAccumulation = scrollAccumulation < 0 ? Math.Min(0, scrollAccumulation + precision) : Math.Max(0, scrollAccumulation - precision); + } } protected override bool OnScroll(ScrollEvent e) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index b355d1f349..01df79c06d 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -187,15 +187,19 @@ namespace osu.Game.Screens.Edit protected override bool OnScroll(ScrollEvent e) { scrollAccumulation += e.ScrollDelta.X + e.ScrollDelta.Y * (e.IsPrecise ? 0.1 : 1); - if (Math.Abs(scrollAccumulation) < 1) - return true; - if (scrollAccumulation > 0) - clock.SeekBackward(!clock.IsRunning); - else - clock.SeekForward(!clock.IsRunning); + const int precision = 1; + + while (Math.Abs(scrollAccumulation) > precision) + { + if (scrollAccumulation > 0) + clock.SeekBackward(!clock.IsRunning); + else + clock.SeekForward(!clock.IsRunning); + + scrollAccumulation = scrollAccumulation < 0 ? Math.Min(0, scrollAccumulation + precision) : Math.Max(0, scrollAccumulation - precision); + } - scrollAccumulation = 0; return true; } From b446a73c0c52de46451e9e2d527f6eebbb6f5d9e Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Fri, 23 Nov 2018 10:06:06 +0900 Subject: [PATCH 17/20] Add brackets Co-Authored-By: peppy --- osu.Game/Screens/Edit/Editor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 01df79c06d..c4fb9dc419 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -186,7 +186,7 @@ namespace osu.Game.Screens.Edit protected override bool OnScroll(ScrollEvent e) { - scrollAccumulation += e.ScrollDelta.X + e.ScrollDelta.Y * (e.IsPrecise ? 0.1 : 1); + scrollAccumulation += (e.ScrollDelta.X + e.ScrollDelta.Y) * (e.IsPrecise ? 0.1 : 1); const int precision = 1; From afa547af848cd20a7bf24842e2d04b257329d07b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Nov 2018 11:00:17 +0900 Subject: [PATCH 18/20] Fix order of ChannelManager dependency caching --- osu.Game/OsuGame.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 4a358da227..2894e096fb 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -50,7 +50,9 @@ namespace osu.Game { public Toolbar Toolbar; - private ChatOverlay chat; + private ChatOverlay chatOverlay; + + private ChannelManager channelManager; private MusicController musicController; @@ -338,12 +340,8 @@ namespace osu.Game //overlay elements loadComponentSingleFile(direct = new DirectOverlay { Depth = -1 }, mainContent.Add); loadComponentSingleFile(social = new SocialOverlay { Depth = -1 }, mainContent.Add); - loadComponentSingleFile(new ChannelManager(), channelManager => - { - dependencies.Cache(channelManager); - AddInternal(channelManager); - }); - loadComponentSingleFile(chat = new ChatOverlay { Depth = -1 }, mainContent.Add); + loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal); + loadComponentSingleFile(chatOverlay = new ChatOverlay { Depth = -1 }, mainContent.Add); loadComponentSingleFile(settings = new MainSettings { GetToolbarHeight = () => ToolbarOffset, @@ -376,7 +374,8 @@ namespace osu.Game dependencies.Cache(onscreenDisplay); dependencies.Cache(social); dependencies.Cache(direct); - dependencies.Cache(chat); + dependencies.Cache(chatOverlay); + dependencies.Cache(channelManager); dependencies.Cache(userProfile); dependencies.Cache(musicController); dependencies.Cache(beatmapSetOverlay); @@ -409,7 +408,7 @@ namespace osu.Game } // ensure only one of these overlays are open at once. - var singleDisplayOverlays = new OverlayContainer[] { chat, social, direct }; + var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, social, direct }; overlays.AddRange(singleDisplayOverlays); foreach (var overlay in singleDisplayOverlays) @@ -534,7 +533,7 @@ namespace osu.Game switch (action) { case GlobalAction.ToggleChat: - chat.ToggleVisibility(); + chatOverlay.ToggleVisibility(); return true; case GlobalAction.ToggleSocial: social.ToggleVisibility(); From ac73844fe02712b5670bcaf4f8ef81c1a499eb58 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 23 Nov 2018 15:18:40 +0900 Subject: [PATCH 19/20] Fix header potentially overflowing the dialog --- osu.Game/Overlays/Dialog/PopupDialog.cs | 27 ++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index f421d2202c..73270c9dde 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -7,12 +7,10 @@ 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.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; using osu.Game.Input.Bindings; using OpenTK; using OpenTK.Graphics; @@ -35,7 +33,7 @@ namespace osu.Game.Overlays.Dialog private readonly Container ring; private readonly FillFlowContainer buttonsContainer; private readonly SpriteIcon icon; - private readonly SpriteText header; + private readonly TextFlowContainer header; private readonly TextFlowContainer body; private bool actionInvoked; @@ -46,10 +44,19 @@ namespace osu.Game.Overlays.Dialog set => icon.Icon = value; } + private string text; + public string HeaderText { - get => header.Text; - set => header.Text = value; + get => text; + set + { + if (text == value) + return; + text = value; + + header.Text = value; + } } public string BodyText @@ -164,18 +171,20 @@ namespace osu.Game.Overlays.Dialog }, }, }, - header = new OsuSpriteText + header = new OsuTextFlowContainer(t => t.TextSize = 25) { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, - TextSize = 25, - Shadow = true, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding(15), + TextAnchor = Anchor.TopCentre, }, body = new OsuTextFlowContainer(t => t.TextSize = 18) { - Padding = new MarginPadding(15), RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Padding = new MarginPadding(15), TextAnchor = Anchor.TopCentre, }, }, From df004d7a49e443cbd100e2e8bb5e2a9f9c8a090f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 23 Nov 2018 15:19:15 +0900 Subject: [PATCH 20/20] Adjust dialog text --- osu.Game/Overlays/Chat/ExternalLinkDialog.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Chat/ExternalLinkDialog.cs b/osu.Game/Overlays/Chat/ExternalLinkDialog.cs index 1b1212af20..b3f7b282a9 100644 --- a/osu.Game/Overlays/Chat/ExternalLinkDialog.cs +++ b/osu.Game/Overlays/Chat/ExternalLinkDialog.cs @@ -11,10 +11,11 @@ namespace osu.Game.Overlays.Chat { public ExternalLinkDialog(string url, Action openExternalLinkAction) { - BodyText = url; + HeaderText = "Just checking..."; + BodyText = $"You are about to leave osu! and open the following link in a web browser:\n\n{url}"; Icon = FontAwesome.fa_warning; - HeaderText = "Are you sure you want to open the following?"; + Buttons = new PopupDialogButton[] { new PopupDialogOkButton