From bb4b5bebf915eaf845d702e10b2285274c510839 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Mon, 25 Dec 2017 15:25:47 +0100 Subject: [PATCH 01/10] fix supporter icon in profile missing its background also it doesn't show up on profiles without supporter anymore --- osu.Game.Tests/Visual/TestCaseUserProfile.cs | 25 +++++++- osu.Game/Overlays/Profile/ProfileHeader.cs | 31 +++------- osu.Game/Overlays/Profile/SupporterIcon.cs | 61 ++++++++++++++++++++ osu.Game/Overlays/UserProfileOverlay.cs | 8 +-- osu.Game/Users/UserPanel.cs | 50 +--------------- osu.Game/osu.Game.csproj | 1 + 6 files changed, 97 insertions(+), 79 deletions(-) create mode 100644 osu.Game/Overlays/Profile/SupporterIcon.cs diff --git a/osu.Game.Tests/Visual/TestCaseUserProfile.cs b/osu.Game.Tests/Visual/TestCaseUserProfile.cs index 38d59f03b5..88627755f4 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfile.cs +++ b/osu.Game.Tests/Visual/TestCaseUserProfile.cs @@ -13,6 +13,8 @@ namespace osu.Game.Tests.Visual { public class TestCaseUserProfile : OsuTestCase { + private readonly TestUserProfileOverlay profile; + public override IReadOnlyList RequiredTypes => new[] { typeof(ProfileHeader), @@ -23,8 +25,7 @@ namespace osu.Game.Tests.Visual public TestCaseUserProfile() { - var profile = new UserProfileOverlay(); - Add(profile); + Add(profile = new TestUserProfileOverlay()); AddStep("Show offline dummy", () => profile.ShowUser(new User { @@ -48,6 +49,9 @@ namespace osu.Game.Tests.Visual Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray() } }, false)); + + checkSupporterTag(false); + AddStep("Show ppy", () => profile.ShowUser(new User { Username = @"peppy", @@ -55,6 +59,9 @@ namespace osu.Game.Tests.Visual Country = new Country { FullName = @"Australia", FlagName = @"AU" }, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg" })); + + checkSupporterTag(true); + AddStep("Show flyte", () => profile.ShowUser(new User { Username = @"flyte", @@ -62,8 +69,22 @@ namespace osu.Game.Tests.Visual Country = new Country { FullName = @"Japan", FlagName = @"JP" }, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg" })); + AddStep("Hide", profile.Hide); AddStep("Show without reload", profile.Show); } + + private void checkSupporterTag(bool isSupporter) + { + AddUntilStep(() => profile.Header.User != null, "wait for load"); + if(isSupporter) + AddAssert("is supporter", () => profile.Header.SupporterTag.Alpha == 1); + else + AddAssert("no supporter", () => profile.Header.SupporterTag.Alpha == 0); + } + + private class TestUserProfileOverlay : UserProfileOverlay { + public new ProfileHeader Header => base.Header; + } } } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index a706799664..f000ca74d4 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -29,7 +29,8 @@ namespace osu.Game.Overlays.Profile private readonly FillFlowContainer scoreText, scoreNumberText; private readonly RankGraph rankGraph; - private readonly Container coverContainer, supporterTag; + public readonly SupporterIcon SupporterTag; + private readonly Container coverContainer; private readonly Sprite levelBadge; private readonly SpriteText levelText; private readonly GradeBadge gradeSSPlus, gradeSS, gradeSPlus, gradeS, gradeA; @@ -94,32 +95,13 @@ namespace osu.Game.Overlays.Profile AutoSizeAxes = Axes.Both, Children = new Drawable[] { - supporterTag = new CircularContainer + SupporterTag = new SupporterIcon { + Alpha = 0, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Y = -75, - Size = new Vector2(25, 25), - Masking = true, - BorderThickness = 3, - BorderColour = Color4.White, - Alpha = 0, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true - }, - new SpriteIcon - { - Icon = FontAwesome.fa_heart, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(12), - } - } + Size = new Vector2(25, 25) }, new LinkFlowContainer.ProfileLink(user) { @@ -328,7 +310,8 @@ namespace osu.Game.Overlays.Profile Depth = float.MaxValue, }, coverContainer.Add); - if (user.IsSupporter) supporterTag.Show(); + if (user.IsSupporter) + SupporterTag.Show(); if (!string.IsNullOrEmpty(user.Colour)) { diff --git a/osu.Game/Overlays/Profile/SupporterIcon.cs b/osu.Game/Overlays/Profile/SupporterIcon.cs new file mode 100644 index 0000000000..570d5a13bb --- /dev/null +++ b/osu.Game/Overlays/Profile/SupporterIcon.cs @@ -0,0 +1,61 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Backgrounds; + +namespace osu.Game.Overlays.Profile +{ + public class SupporterIcon : CircularContainer + { + private readonly Box background; + + public SupporterIcon() + { + Masking = true; + Children = new Drawable[] + { + new Box { RelativeSizeAxes = Axes.Both }, + new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(0.8f), + Masking = true, + Children = new Drawable[] + { + background = new Box { RelativeSizeAxes = Axes.Both }, + new Triangles + { + TriangleScale = 0.2f, + ColourLight = OsuColour.FromHex(@"ff7db7"), + ColourDark = OsuColour.FromHex(@"de5b95"), + RelativeSizeAxes = Axes.Both, + Velocity = 0.3f, + }, + } + }, + new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Icon = FontAwesome.fa_heart, + Scale = new Vector2(0.45f), + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.Pink; + } + } +} diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 7374a9aa44..9aa660147a 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -28,7 +28,7 @@ namespace osu.Game.Overlays private ProfileSection[] sections; private GetUserRequest userReq; private APIAccess api; - private ProfileHeader header; + protected ProfileHeader Header; private SectionsContainer sectionsContainer; private ProfileTabControl tabs; @@ -113,12 +113,12 @@ namespace osu.Game.Overlays Colour = OsuColour.Gray(0.2f) }); - header = new ProfileHeader(user); + Header = new ProfileHeader(user); Add(sectionsContainer = new SectionsContainer { RelativeSizeAxes = Axes.Both, - ExpandableHeader = header, + ExpandableHeader = Header, FixedHeader = tabs, HeaderBackground = new Box { @@ -169,7 +169,7 @@ namespace osu.Game.Overlays private void userLoadComplete(User user) { - header.User = user; + Header.User = user; foreach (string id in user.ProfileOrder) { diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index d056afcf54..a2cc8e8d49 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -16,8 +16,8 @@ using osu.Game.Overlays; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Cursor; -using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; +using osu.Game.Overlays.Profile; namespace osu.Game.Users { @@ -220,53 +220,5 @@ namespace osu.Game.Users { new OsuMenuItem("View Profile", MenuItemType.Highlighted, ViewProfile), }; - - private class SupporterIcon : CircularContainer - { - private readonly Box background; - - public SupporterIcon() - { - Masking = true; - Children = new Drawable[] - { - new Box { RelativeSizeAxes = Axes.Both }, - new CircularContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.8f), - Masking = true, - Children = new Drawable[] - { - background = new Box { RelativeSizeAxes = Axes.Both }, - new Triangles - { - TriangleScale = 0.2f, - ColourLight = OsuColour.FromHex(@"ff7db7"), - ColourDark = OsuColour.FromHex(@"de5b95"), - RelativeSizeAxes = Axes.Both, - Velocity = 0.3f, - }, - } - }, - new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Icon = FontAwesome.fa_heart, - Scale = new Vector2(0.45f), - } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = colours.Pink; - } - } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 94678106bf..18134582f3 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -268,6 +268,7 @@ + From 48e55a06865ab8cf50987edfb588c3d6b7ba3d71 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Mon, 25 Dec 2017 16:52:17 +0100 Subject: [PATCH 02/10] fix formatting and test add missing line --- osu.Game.Tests/Visual/TestCaseUserProfile.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseUserProfile.cs b/osu.Game.Tests/Visual/TestCaseUserProfile.cs index 88627755f4..13b6509740 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfile.cs +++ b/osu.Game.Tests/Visual/TestCaseUserProfile.cs @@ -26,6 +26,11 @@ namespace osu.Game.Tests.Visual public TestCaseUserProfile() { Add(profile = new TestUserProfileOverlay()); + } + + protected override void LoadComplete() + { + base.LoadComplete(); AddStep("Show offline dummy", () => profile.ShowUser(new User { @@ -77,13 +82,14 @@ namespace osu.Game.Tests.Visual private void checkSupporterTag(bool isSupporter) { AddUntilStep(() => profile.Header.User != null, "wait for load"); - if(isSupporter) + if (isSupporter) AddAssert("is supporter", () => profile.Header.SupporterTag.Alpha == 1); else AddAssert("no supporter", () => profile.Header.SupporterTag.Alpha == 0); } - private class TestUserProfileOverlay : UserProfileOverlay { + private class TestUserProfileOverlay : UserProfileOverlay + { public new ProfileHeader Header => base.Header; } } From dff082ed940ad1cd93e0a52f62bd8dd46a5546f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2017 01:12:46 +0900 Subject: [PATCH 03/10] Make toolbar testable and add the most basic of visual tests --- osu.Game.Tests/Visual/TestCaseToolbar.cs | 25 +++++++++++++++++++ osu.Game.Tests/osu.Game.Tests.csproj | 1 + .../Overlays/Toolbar/ToolbarChatButton.cs | 2 +- .../Overlays/Toolbar/ToolbarDirectButton.cs | 2 +- .../Overlays/Toolbar/ToolbarModeSelector.cs | 7 ++++-- .../Overlays/Toolbar/ToolbarMusicButton.cs | 2 +- .../Toolbar/ToolbarNotificationButton.cs | 2 +- .../Toolbar/ToolbarOverlayToggleButton.cs | 7 ++++-- .../Overlays/Toolbar/ToolbarSettingsButton.cs | 2 +- .../Overlays/Toolbar/ToolbarSocialButton.cs | 2 +- 10 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseToolbar.cs diff --git a/osu.Game.Tests/Visual/TestCaseToolbar.cs b/osu.Game.Tests/Visual/TestCaseToolbar.cs new file mode 100644 index 0000000000..9045249b9a --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseToolbar.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics.Containers; +using osu.Game.Overlays.Toolbar; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseToolbar : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ToolbarButton), + typeof(ToolbarModeSelector), + typeof(ToolbarModeButton), + }; + + public TestCaseToolbar() + { + Add(new Toolbar { State = Visibility.Visible }); + } + } +} diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index ff012bb6e2..71703d264a 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -148,6 +148,7 @@ + diff --git a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs index ed206e7e1d..b0171feb30 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Toolbar SetIcon(FontAwesome.fa_comments); } - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(ChatOverlay chat) { StateContainer = chat; diff --git a/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs b/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs index 7d25440e2c..5c64ae69ec 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Toolbar SetIcon(FontAwesome.fa_osu_chevron_down_o); } - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(DirectOverlay direct) { StateContainer = direct; diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index 319dd63bc9..f38c772890 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -64,7 +64,7 @@ namespace osu.Game.Overlays.Toolbar }; } - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(RulesetStore rulesets, OsuGame game) { foreach (var r in rulesets.AvailableRulesets) @@ -81,7 +81,10 @@ namespace osu.Game.Overlays.Toolbar ruleset.ValueChanged += rulesetChanged; ruleset.DisabledChanged += disabledChanged; - ruleset.BindTo(game.Ruleset); + if (game != null) + ruleset.BindTo(game.Ruleset); + else + ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(); } public override bool HandleInput => !ruleset.Disabled; diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index d150aacdf9..81c57a984f 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Toolbar Icon = FontAwesome.fa_music; } - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(MusicController music) { StateContainer = music; diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index e11a22d675..dbe8b48424 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Toolbar TooltipSub = "Waiting for 'ya"; } - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(NotificationOverlay notificationOverlay) { StateContainer = notificationOverlay; diff --git a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs index 69fdd27d5d..59314b8771 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs @@ -21,8 +21,11 @@ namespace osu.Game.Overlays.Toolbar set { stateContainer = value; - Action = stateContainer.ToggleVisibility; - stateContainer.StateChanged += stateChanged; + if (stateContainer != null) + { + Action = stateContainer.ToggleVisibility; + stateContainer.StateChanged += stateChanged; + } } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs index cf4f664e81..d0d76dd5d2 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs @@ -15,7 +15,7 @@ namespace osu.Game.Overlays.Toolbar TooltipSub = "Change your settings"; } - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(SettingsOverlay settings) { StateContainer = settings; diff --git a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs index 234d6f0f9a..74d1da4384 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Toolbar Icon = FontAwesome.fa_users; } - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(SocialOverlay chat) { StateContainer = chat; From bb33d0211a5802c6706c3a18570cbc16ffa4c227 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2017 01:36:58 +0900 Subject: [PATCH 04/10] Add a count of unread notifications to the toolbar --- osu.Game.Tests/Visual/TestCaseToolbar.cs | 16 ++++- .../Toolbar/ToolbarNotificationButton.cs | 64 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseToolbar.cs b/osu.Game.Tests/Visual/TestCaseToolbar.cs index 9045249b9a..9f538af09b 100644 --- a/osu.Game.Tests/Visual/TestCaseToolbar.cs +++ b/osu.Game.Tests/Visual/TestCaseToolbar.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics.Containers; using osu.Game.Overlays.Toolbar; @@ -15,11 +16,24 @@ namespace osu.Game.Tests.Visual typeof(ToolbarButton), typeof(ToolbarModeSelector), typeof(ToolbarModeButton), + typeof(ToolbarNotificationButton), }; public TestCaseToolbar() { - Add(new Toolbar { State = Visibility.Visible }); + var toolbar = new Toolbar { State = Visibility.Visible }; + + Add(toolbar); + + var notificationButton = toolbar.Children.OfType().Last().Children.OfType().First(); + + void setNotifications(int count) => AddStep($"set notification count to {count}", () => notificationButton.NotificationCount.Value = count); + + setNotifications(1); + setNotifications(2); + setNotifications(3); + setNotifications(0); + setNotifications(144); } } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index dbe8b48424..78a04d156a 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs @@ -2,8 +2,14 @@ // 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.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Overlays.Toolbar { @@ -11,17 +17,75 @@ namespace osu.Game.Overlays.Toolbar { protected override Anchor TooltipAnchor => Anchor.TopRight; + public BindableInt NotificationCount = new BindableInt(); + + private CountCircle countDisplay; + public ToolbarNotificationButton() { Icon = FontAwesome.fa_bars; TooltipMain = "Notifications"; TooltipSub = "Waiting for 'ya"; + + Add(countDisplay = new CountCircle + { + Alpha = 0, + Height = 16, + RelativePositionAxes = Axes.Both, + Origin = Anchor.TopCentre, + Position = new Vector2(0.7f, 0.05f), + }); } [BackgroundDependencyLoader(true)] private void load(NotificationOverlay notificationOverlay) { StateContainer = notificationOverlay; + + NotificationCount.ValueChanged += count => + { + if (count == 0) + countDisplay.FadeOut(200, Easing.OutQuint); + else + countDisplay.FadeIn(200, Easing.OutQuint); + + countDisplay.Count = count; + }; + } + + private class CountCircle : CompositeDrawable + { + private readonly OsuSpriteText count; + + public int Count + { + set { count.Text = value.ToString("#,0"); } + } + + public CountCircle() + { + AutoSizeAxes = Axes.X; + + InternalChildren = new Drawable[] + { + new Circle + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Red + }, + count = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Y = -1, + TextSize = 14, + Padding = new MarginPadding(5), + Colour = Color4.White, + UseFullGlyphHeight = true, + Font = "Exo2.0-Bold", + } + }; + } } } } From 1fc240f6c594ad7f1469f4276a0778034c59bb2e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2017 01:50:05 +0900 Subject: [PATCH 05/10] Expose unread notification count --- .../Visual/TestCaseNotificationOverlay.cs | 7 ++++ osu.Game/Overlays/NotificationOverlay.cs | 42 ++++++++++++------- .../Notifications/NotificationSection.cs | 4 +- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs b/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs index b93c2d812f..233914767d 100644 --- a/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; @@ -25,6 +26,12 @@ namespace osu.Game.Tests.Visual Origin = Anchor.TopRight }); + SpriteText displayedCount = new SpriteText(); + + Content.Add(displayedCount); + + manager.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count}"; }; + AddStep(@"toggle", manager.ToggleVisibility); AddStep(@"simple #1", sendHelloNotification); AddStep(@"simple #2", sendAmazingNotification); diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index a4b5486596..2f1c3285ef 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -11,6 +11,7 @@ using OpenTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; using System; +using osu.Framework.Configuration; namespace osu.Game.Overlays { @@ -75,34 +76,38 @@ namespace osu.Game.Overlays }; } + private int totalCount => sections.Select(c => c.DisplayedCount).Sum(); + private int unreadCount => sections.Select(c => c.UnreadCount).Sum(); + + public readonly BindableInt UnreadCount = new BindableInt(); + private int runningDepth; private void notificationClosed() { // hide ourselves if all notifications have been dismissed. - if (sections.Select(c => c.DisplayedCount).Sum() == 0) + if (totalCount == 0) State = Visibility.Hidden; + + updateCounts(); } - public void Post(Notification notification) + public void Post(Notification notification) => Schedule(() => { - Schedule(() => - { - State = Visibility.Visible; + ++runningDepth; + notification.Depth = notification.DisplayOnTop ? runningDepth : -runningDepth; - ++runningDepth; - notification.Depth = notification.DisplayOnTop ? runningDepth : -runningDepth; + notification.Closed += notificationClosed; - notification.Closed += notificationClosed; + var hasCompletionTarget = notification as IHasCompletionTarget; + if (hasCompletionTarget != null) + hasCompletionTarget.CompletionTarget = Post; - var hasCompletionTarget = notification as IHasCompletionTarget; - if (hasCompletionTarget != null) - hasCompletionTarget.CompletionTarget = Post; + var ourType = notification.GetType(); + sections.Children.FirstOrDefault(s => s.AcceptTypes.Any(accept => accept.IsAssignableFrom(ourType)))?.Add(notification); - var ourType = notification.GetType(); - sections.Children.FirstOrDefault(s => s.AcceptTypes.Any(accept => accept.IsAssignableFrom(ourType)))?.Add(notification); - }); - } + updateCounts(); + }); protected override void PopIn() { @@ -122,9 +127,16 @@ namespace osu.Game.Overlays this.FadeTo(0, TRANSITION_LENGTH, Easing.OutQuint); } + private void updateCounts() + { + UnreadCount.Value = unreadCount; + } + private void markAllRead() { sections.Children.ForEach(s => s.MarkAllRead()); + + updateCounts(); } protected override void UpdateAfterChildren() diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index 09768ba0ea..2bd0321d12 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -26,6 +26,8 @@ namespace osu.Game.Overlays.Notifications public int DisplayedCount => notifications.Count(n => !n.WasClosed); + public int UnreadCount => notifications.Count(n => !n.WasClosed && !n.Read); + public void Add(Notification notification) => notifications.Add(notification); public IEnumerable AcceptTypes; @@ -157,4 +159,4 @@ namespace osu.Game.Overlays.Notifications notifications?.Children.ForEach(n => n.Read = true); } } -} \ No newline at end of file +} From 0886107ec911c79d6d3f25317b31c0586ddc0ba2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2017 01:56:57 +0900 Subject: [PATCH 06/10] Connect counter with button display --- .../Toolbar/ToolbarNotificationButton.cs | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index 78a04d156a..faf802f5e7 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Toolbar public BindableInt NotificationCount = new BindableInt(); - private CountCircle countDisplay; + private readonly CountCircle countDisplay; public ToolbarNotificationButton() { @@ -32,8 +32,8 @@ namespace osu.Game.Overlays.Toolbar Alpha = 0, Height = 16, RelativePositionAxes = Axes.Both, - Origin = Anchor.TopCentre, - Position = new Vector2(0.7f, 0.05f), + Origin = Anchor.Centre, + Position = new Vector2(0.7f, 0.25f), }); } @@ -42,24 +42,34 @@ namespace osu.Game.Overlays.Toolbar { StateContainer = notificationOverlay; + if (notificationOverlay != null) + NotificationCount.BindTo(notificationOverlay.UnreadCount); + NotificationCount.ValueChanged += count => { if (count == 0) countDisplay.FadeOut(200, Easing.OutQuint); else + { + countDisplay.Count = count; countDisplay.FadeIn(200, Easing.OutQuint); - - countDisplay.Count = count; + } }; } private class CountCircle : CompositeDrawable { private readonly OsuSpriteText count; + private readonly Circle circle; public int Count { - set { count.Text = value.ToString("#,0"); } + set + { + count.Text = value.ToString("#,0"); + circle.FlashColour(Color4.White, 600, Easing.OutQuint); + this.ScaleTo(1.1f).Then().ScaleTo(1, 600, Easing.OutElastic); + } } public CountCircle() @@ -68,7 +78,7 @@ namespace osu.Game.Overlays.Toolbar InternalChildren = new Drawable[] { - new Circle + circle = new Circle { RelativeSizeAxes = Axes.Both, Colour = Color4.Red From d8f084474216cccb9add01ec3ec40f282bc42bce Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Dec 2017 11:24:13 +0900 Subject: [PATCH 07/10] Fix null reference in release builds Intro may not be initialised yet --- osu.Game/OsuGame.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 67f6e6f4e2..fe7ca77d44 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -272,7 +272,7 @@ namespace osu.Game }; } - Action stateChanged = delegate + void updateScreenOffset() { float offset = 0; @@ -281,11 +281,11 @@ namespace osu.Game if (notifications.State == Visibility.Visible) offset -= ToolbarButton.WIDTH / 2; - intro.MoveToX(offset, SettingsOverlay.TRANSITION_LENGTH, Easing.OutQuint); - }; + screenStack.MoveToX(offset, SettingsOverlay.TRANSITION_LENGTH, Easing.OutQuint); + } - settings.StateChanged += stateChanged; - notifications.StateChanged += stateChanged; + settings.StateChanged += _ => updateScreenOffset(); + notifications.StateChanged += _ => updateScreenOffset(); Cursor.State = Visibility.Hidden; } From c737e5245e0442d097d7e9efd6cd6c18cd9dfc60 Mon Sep 17 00:00:00 2001 From: FreezyLemon Date: Tue, 26 Dec 2017 01:50:05 +0100 Subject: [PATCH 08/10] Removed unnecessary SelectNext() call and change to dummy map when no items present --- osu.Game/Screens/Select/BeatmapCarousel.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index be176c1459..802667e6a0 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -142,7 +142,6 @@ namespace osu.Game.Screens.Select if (newSet == null) { itemsCache.Invalidate(); - SelectNext(); return; } @@ -512,7 +511,7 @@ namespace osu.Game.Screens.Select currentY += DrawHeight / 2; scrollableContent.Height = currentY; - if (selectedBeatmapSet != null && selectedBeatmapSet.State.Value != CarouselItemState.Selected) + if (!Items.Any() || selectedBeatmapSet != null && selectedBeatmapSet.State.Value != CarouselItemState.Selected) { selectedBeatmapSet = null; SelectionChanged?.Invoke(null); From c82273572430b6bcefa1b3dbfe45644e543fed2f Mon Sep 17 00:00:00 2001 From: FreezyLemon Date: Tue, 26 Dec 2017 03:57:18 +0100 Subject: [PATCH 09/10] Added tests for hiding diffs (and especially the last visible diff) --- .../Visual/TestCaseBeatmapCarousel.cs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs index 639befef74..c09b987407 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs @@ -70,6 +70,7 @@ namespace osu.Game.Tests.Visual testRemoveAll(); testEmptyTraversal(); + testHiding(); } private void ensureRandomFetchSuccess() => @@ -295,6 +296,40 @@ namespace osu.Game.Tests.Visual checkNoSelection(); } + private void testHiding() + { + var hidingSet = createTestBeatmapSet(1); + hidingSet.Beatmaps[1].Hidden = true; + AddStep("Add set with diff 2 hidden", () => carousel.UpdateBeatmapSet(hidingSet)); + setSelected(1, 1); + + checkVisibleItemCount(true, 2); + advanceSelection(true); + checkSelected(1, 3); + + setHidden(3); + checkSelected(1, 1); + + setHidden(2, false); + advanceSelection(true); + checkSelected(1, 2); + + setHidden(1); + checkSelected(1, 2); + + setHidden(2); + checkNoSelection(); + + void setHidden(int diff, bool hidden = true) + { + AddStep((hidden ? "" : "un") + $"hide diff {diff}", () => + { + hidingSet.Beatmaps[diff - 1].Hidden = hidden; + carousel.UpdateBeatmapSet(hidingSet); + }); + } + } + private BeatmapSetInfo createTestBeatmapSet(int i) { return new BeatmapSetInfo From 09ce24a7dba54deb34d629e75eee48978d1f26a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2017 13:41:02 +0900 Subject: [PATCH 10/10] Switch to a better way of deciding on null selection This avoids `SelectionChanged` potentially being invoked multiple times after `selectedBeatmapSet` is already `null`. --- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 802667e6a0..87edfe9692 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -511,7 +511,7 @@ namespace osu.Game.Screens.Select currentY += DrawHeight / 2; scrollableContent.Height = currentY; - if (!Items.Any() || selectedBeatmapSet != null && selectedBeatmapSet.State.Value != CarouselItemState.Selected) + if (selectedBeatmapSet != null && (selectedBeatmap == null || selectedBeatmapSet.State.Value != CarouselItemState.Selected)) { selectedBeatmapSet = null; SelectionChanged?.Invoke(null);