From a70bfca501312bc587c230064a6269b20a714c82 Mon Sep 17 00:00:00 2001 From: Joshua Hegedus Date: Thu, 2 Nov 2023 09:16:25 +0100 Subject: [PATCH 01/20] added usergrid for tooltip --- osu.Game/Users/Drawables/ClickableAvatar.cs | 33 ++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 677a8fff36..0ed9f56cc7 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -3,16 +3,27 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics.Containers; using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; +using osuTK; namespace osu.Game.Users.Drawables { - public partial class ClickableAvatar : OsuClickableContainer + public partial class ClickableAvatar : OsuClickableContainer, IHasCustomTooltip { + public ITooltip GetCustomTooltip() => new UserGridPanelTooltip(); + + public UserGridPanel TooltipContent => new UserGridPanel(user!) + { + Width = 300 + }; + public override LocalisableString TooltipText { get @@ -67,5 +78,25 @@ namespace osu.Game.Users.Drawables return base.OnClick(e); } + + private partial class UserGridPanelTooltip : VisibilityContainer, ITooltip + { + private UserGridPanel? displayedUser; + + protected override void PopIn() + { + Child = displayedUser; + this.FadeIn(20, Easing.OutQuint); + } + + protected override void PopOut() => this.FadeOut(80, Easing.OutQuint); + + public void Move(Vector2 pos) => Position = pos; + + public void SetContent(UserGridPanel userGridPanel) + { + displayedUser = userGridPanel; + } + } } } From ec290ae953c9dffec44bb71e1fcde4e0785ef843 Mon Sep 17 00:00:00 2001 From: Joshua Hegedus Date: Sat, 4 Nov 2023 19:03:23 +0100 Subject: [PATCH 02/20] added tests --- .../Online/TestSceneUserClickableAvatar.cs | 125 ++++++++++++++++++ osu.Game/Users/Drawables/ClickableAvatar.cs | 21 --- osu.Game/Users/Drawables/UpdateableAvatar.cs | 1 - 3 files changed, 125 insertions(+), 22 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs new file mode 100644 index 0000000000..13f559ac09 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs @@ -0,0 +1,125 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Testing; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Users; +using osu.Game.Users.Drawables; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.Online +{ + public partial class TestSceneUserClickableAvatar : OsuManualInputManagerTestScene + { + [SetUp] + public void SetUp() => Schedule(() => + { + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Spacing = new Vector2(10f), + Children = new Drawable[] + { + new ClickableAvatar(new APIUser + { + Username = @"flyte", Id = 3103765, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg" + }) + { + Width = 50, + Height = 50, + CornerRadius = 10, + Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, Radius = 1, Colour = Color4.Black.Opacity(0.2f), + }, + }, + new ClickableAvatar(new APIUser + { + Username = @"peppy", Id = 2, Colour = "99EB47", CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", + }) + { + Width = 50, + Height = 50, + CornerRadius = 10, + Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, Radius = 1, Colour = Color4.Black.Opacity(0.2f), + }, + }, + new ClickableAvatar(new APIUser + { + Username = @"flyte", + Id = 3103765, + CountryCode = CountryCode.JP, + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg", + Status = + { + Value = new UserStatusOnline() + } + }) + { + Width = 50, + Height = 50, + CornerRadius = 10, + Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, Radius = 1, Colour = Color4.Black.Opacity(0.2f), + }, + }, + }, + }; + }); + + [Test] + public void TestClickableAvatarHover() + { + AddStep($"click {1}. {nameof(ClickableAvatar)}", () => + { + var targets = this.ChildrenOfType().ToList(); + if (targets.Count < 1) + return; + + InputManager.MoveMouseTo(targets[0]); + }); + AddWaitStep("wait for tooltip to show", 5); + AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + AddWaitStep("wait for tooltip to hide", 3); + + AddStep($"click {2}. {nameof(ClickableAvatar)}", () => + { + var targets = this.ChildrenOfType().ToList(); + if (targets.Count < 2) + return; + + InputManager.MoveMouseTo(targets[1]); + }); + AddWaitStep("wait for tooltip to show", 5); + AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + AddWaitStep("wait for tooltip to hide", 3); + + AddStep($"click {3}. {nameof(ClickableAvatar)}", () => + { + var targets = this.ChildrenOfType().ToList(); + if (targets.Count < 3) + return; + + InputManager.MoveMouseTo(targets[2]); + }); + AddWaitStep("wait for tooltip to show", 5); + AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + AddWaitStep("wait for tooltip to hide", 3); + } + } +} diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 0ed9f56cc7..d6c6afba0b 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -1,15 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; -using osu.Framework.Localisation; using osu.Game.Graphics.Containers; -using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; using osuTK; @@ -24,24 +21,6 @@ namespace osu.Game.Users.Drawables Width = 300 }; - public override LocalisableString TooltipText - { - get - { - if (!Enabled.Value) - return string.Empty; - - return ShowUsernameTooltip ? (user?.Username ?? string.Empty) : ContextMenuStrings.ViewProfile; - } - set => throw new NotSupportedException(); - } - - /// - /// By default, the tooltip will show "view profile" as avatars are usually displayed next to a username. - /// Setting this to true exposes the username via tooltip for special cases where this is not true. - /// - public bool ShowUsernameTooltip { get; set; } - private readonly APIUser? user; [Resolved] diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index c659685807..58b3646995 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -74,7 +74,6 @@ namespace osu.Game.Users.Drawables { return new ClickableAvatar(user) { - ShowUsernameTooltip = showUsernameTooltip, RelativeSizeAxes = Axes.Both, }; } From 40d081ee2de0940600f94ff126259b019622483b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 6 Nov 2023 16:05:50 +0900 Subject: [PATCH 03/20] Add note about `Width` requirement in `UserGridPanel` --- osu.Game/Users/UserGridPanel.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Users/UserGridPanel.cs b/osu.Game/Users/UserGridPanel.cs index f4ec1475b1..aac2315b2f 100644 --- a/osu.Game/Users/UserGridPanel.cs +++ b/osu.Game/Users/UserGridPanel.cs @@ -10,6 +10,10 @@ using osuTK; namespace osu.Game.Users { + /// + /// A user "card", commonly used in a grid layout or in popovers. + /// Comes with a preset height, but width must be specified. + /// public partial class UserGridPanel : ExtendedUserPanel { private const int margin = 10; From b45d8c785cd662796c6098f72aadf589b99161e4 Mon Sep 17 00:00:00 2001 From: Joshua Hegedus Date: Mon, 6 Nov 2023 08:38:34 +0100 Subject: [PATCH 04/20] fixed review findings --- .../Online/TestSceneUserClickableAvatar.cs | 26 +++++++++++++++++++ osu.Game/Users/Drawables/ClickableAvatar.cs | 21 +++++++++++++++ osu.Game/Users/Drawables/UpdateableAvatar.cs | 1 + 3 files changed, 48 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs index 13f559ac09..a24581f7ed 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs @@ -78,6 +78,8 @@ namespace osu.Game.Tests.Visual.Online Type = EdgeEffectType.Shadow, Radius = 1, Colour = Color4.Black.Opacity(0.2f), }, }, + new ClickableAvatar(), + new ClickableAvatar(), }, }; }); @@ -120,6 +122,30 @@ namespace osu.Game.Tests.Visual.Online AddWaitStep("wait for tooltip to show", 5); AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); AddWaitStep("wait for tooltip to hide", 3); + + AddStep($"click null user {4}. {nameof(ClickableAvatar)}", () => + { + var targets = this.ChildrenOfType().ToList(); + if (targets.Count < 4) + return; + + InputManager.MoveMouseTo(targets[3]); + }); + AddWaitStep("wait for tooltip to show", 5); + AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + AddWaitStep("wait for tooltip to hide", 3); + + AddStep($"click null user {5}. {nameof(ClickableAvatar)}", () => + { + var targets = this.ChildrenOfType().ToList(); + if (targets.Count < 5) + return; + + InputManager.MoveMouseTo(targets[4]); + }); + AddWaitStep("wait for tooltip to show", 5); + AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + AddWaitStep("wait for tooltip to hide", 3); } } } diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index d6c6afba0b..0ed9f56cc7 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -1,12 +1,15 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Game.Graphics.Containers; +using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; using osuTK; @@ -21,6 +24,24 @@ namespace osu.Game.Users.Drawables Width = 300 }; + public override LocalisableString TooltipText + { + get + { + if (!Enabled.Value) + return string.Empty; + + return ShowUsernameTooltip ? (user?.Username ?? string.Empty) : ContextMenuStrings.ViewProfile; + } + set => throw new NotSupportedException(); + } + + /// + /// By default, the tooltip will show "view profile" as avatars are usually displayed next to a username. + /// Setting this to true exposes the username via tooltip for special cases where this is not true. + /// + public bool ShowUsernameTooltip { get; set; } + private readonly APIUser? user; [Resolved] diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index 58b3646995..711e7ab799 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -75,6 +75,7 @@ namespace osu.Game.Users.Drawables return new ClickableAvatar(user) { RelativeSizeAxes = Axes.Both, + ShowUsernameTooltip = showUsernameTooltip, }; } else From 4a70f2435c574b82829a5d2508ae29f7d2e3a2fb Mon Sep 17 00:00:00 2001 From: Joshua Hegedus Date: Mon, 6 Nov 2023 09:22:50 +0100 Subject: [PATCH 05/20] fixed showUsernameTooltip --- .../OnlinePlay/Components/ParticipantsList.cs | 2 +- .../DrawableRoomParticipantsList.cs | 2 +- osu.Game/Users/Drawables/ClickableAvatar.cs | 21 ------------------- osu.Game/Users/Drawables/UpdateableAvatar.cs | 6 +----- 4 files changed, 3 insertions(+), 28 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs index 00f0889cc8..cb1a846d6c 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs @@ -115,7 +115,7 @@ namespace osu.Game.Screens.OnlinePlay.Components RelativeSizeAxes = Axes.Both, Colour = Color4Extensions.FromHex(@"27252d"), }, - avatar = new UpdateableAvatar(showUsernameTooltip: true) { RelativeSizeAxes = Axes.Both }, + avatar = new UpdateableAvatar { RelativeSizeAxes = Axes.Both }, }; } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs index 06f9f35479..1814f5359f 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs @@ -289,7 +289,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components set => avatar.User = value; } - private readonly UpdateableAvatar avatar = new UpdateableAvatar(showUsernameTooltip: true) { RelativeSizeAxes = Axes.Both }; + private readonly UpdateableAvatar avatar = new UpdateableAvatar { RelativeSizeAxes = Axes.Both }; [BackgroundDependencyLoader] private void load(OverlayColourProvider colours) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 0ed9f56cc7..d6c6afba0b 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -1,15 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; -using osu.Framework.Localisation; using osu.Game.Graphics.Containers; -using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; using osuTK; @@ -24,24 +21,6 @@ namespace osu.Game.Users.Drawables Width = 300 }; - public override LocalisableString TooltipText - { - get - { - if (!Enabled.Value) - return string.Empty; - - return ShowUsernameTooltip ? (user?.Username ?? string.Empty) : ContextMenuStrings.ViewProfile; - } - set => throw new NotSupportedException(); - } - - /// - /// By default, the tooltip will show "view profile" as avatars are usually displayed next to a username. - /// Setting this to true exposes the username via tooltip for special cases where this is not true. - /// - public bool ShowUsernameTooltip { get; set; } - private readonly APIUser? user; [Resolved] diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index 711e7ab799..3c72d7f7e0 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -46,7 +46,6 @@ namespace osu.Game.Users.Drawables protected override double LoadDelay => 200; private readonly bool isInteractive; - private readonly bool showUsernameTooltip; private readonly bool showGuestOnNull; /// @@ -54,12 +53,10 @@ namespace osu.Game.Users.Drawables /// /// The initial user to display. /// If set to true, hover/click sounds will play and clicking the avatar will open the user's profile. - /// Whether to show the username rather than "view profile" on the tooltip. (note: this only applies if is also true) /// Whether to show a default guest representation on null user (as opposed to nothing). - public UpdateableAvatar(APIUser? user = null, bool isInteractive = true, bool showUsernameTooltip = false, bool showGuestOnNull = true) + public UpdateableAvatar(APIUser? user = null, bool isInteractive = true, bool showGuestOnNull = true) { this.isInteractive = isInteractive; - this.showUsernameTooltip = showUsernameTooltip; this.showGuestOnNull = showGuestOnNull; User = user; @@ -75,7 +72,6 @@ namespace osu.Game.Users.Drawables return new ClickableAvatar(user) { RelativeSizeAxes = Axes.Both, - ShowUsernameTooltip = showUsernameTooltip, }; } else From 718492a0b7d9c38b32102095c84393fbe5a792d9 Mon Sep 17 00:00:00 2001 From: Joshua Hegedus Date: Mon, 6 Nov 2023 11:29:15 +0100 Subject: [PATCH 06/20] fixed DRY --- .../Online/TestSceneUserClickableAvatar.cs | 83 +++++++------------ 1 file changed, 32 insertions(+), 51 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs index a24581f7ed..72870a5647 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs @@ -27,59 +27,14 @@ namespace osu.Game.Tests.Visual.Online Anchor = Anchor.Centre, Origin = Anchor.Centre, Spacing = new Vector2(10f), - Children = new Drawable[] + Children = new[] { - new ClickableAvatar(new APIUser - { - Username = @"flyte", Id = 3103765, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg" - }) - { - Width = 50, - Height = 50, - CornerRadius = 10, - Masking = true, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, Radius = 1, Colour = Color4.Black.Opacity(0.2f), - }, - }, - new ClickableAvatar(new APIUser - { - Username = @"peppy", Id = 2, Colour = "99EB47", CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", - }) - { - Width = 50, - Height = 50, - CornerRadius = 10, - Masking = true, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, Radius = 1, Colour = Color4.Black.Opacity(0.2f), - }, - }, - new ClickableAvatar(new APIUser - { - Username = @"flyte", - Id = 3103765, - CountryCode = CountryCode.JP, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg", - Status = - { - Value = new UserStatusOnline() - } - }) - { - Width = 50, - Height = 50, - CornerRadius = 10, - Masking = true, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, Radius = 1, Colour = Color4.Black.Opacity(0.2f), - }, - }, - new ClickableAvatar(), + generateUser(@"peppy", 2, CountryCode.AU, @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", "99EB47"), + generateUser(@"flyte", 3103765, CountryCode.JP, @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"), + generateUser(@"flyte", 3103765, CountryCode.JP, @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"), new ClickableAvatar(), + new UpdateableAvatar(), + new UpdateableAvatar(), }, }; }); @@ -147,5 +102,31 @@ namespace osu.Game.Tests.Visual.Online AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); AddWaitStep("wait for tooltip to hide", 3); } + + private Drawable generateUser(string username, int id, CountryCode countryCode, string cover, string? color = null) + { + return new ClickableAvatar(new APIUser + { + Username = username, + Id = id, + CountryCode = countryCode, + CoverUrl = cover, + Colour = color ?? "000000", + Status = + { + Value = new UserStatusOnline() + } + }) + { + Width = 50, + Height = 50, + CornerRadius = 10, + Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, Radius = 1, Colour = Color4.Black.Opacity(0.2f), + }, + }; + } } } From 034f53da4b1d79220d8af95055a203076ab88c87 Mon Sep 17 00:00:00 2001 From: Joshua Hegedus Date: Mon, 6 Nov 2023 11:54:57 +0100 Subject: [PATCH 07/20] added isEnabled to tooltip --- osu.Game/Users/Drawables/ClickableAvatar.cs | 16 +++++++++++++++- osu.Game/Users/Drawables/UpdateableAvatar.cs | 5 ++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index d6c6afba0b..0520f62665 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -14,13 +14,15 @@ namespace osu.Game.Users.Drawables { public partial class ClickableAvatar : OsuClickableContainer, IHasCustomTooltip { - public ITooltip GetCustomTooltip() => new UserGridPanelTooltip(); + public ITooltip GetCustomTooltip() => new UserGridPanelTooltip(IsTooltipEnabled); public UserGridPanel TooltipContent => new UserGridPanel(user!) { Width = 300 }; + public bool IsTooltipEnabled; + private readonly APIUser? user; [Resolved] @@ -33,6 +35,7 @@ namespace osu.Game.Users.Drawables public ClickableAvatar(APIUser? user = null) { this.user = user; + IsTooltipEnabled = true; if (user?.Id != APIUser.SYSTEM_USER_ID) Action = openProfile; @@ -60,10 +63,21 @@ namespace osu.Game.Users.Drawables private partial class UserGridPanelTooltip : VisibilityContainer, ITooltip { + private readonly bool isEnabled; private UserGridPanel? displayedUser; + public UserGridPanelTooltip(bool isEnabled = true) + { + this.isEnabled = isEnabled; + } + protected override void PopIn() { + if (displayedUser is null || !isEnabled) + { + return; + } + Child = displayedUser; this.FadeIn(20, Easing.OutQuint); } diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index 3c72d7f7e0..a970997056 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -47,17 +47,20 @@ namespace osu.Game.Users.Drawables private readonly bool isInteractive; private readonly bool showGuestOnNull; + private readonly bool showUserPanel; /// /// Construct a new UpdateableAvatar. /// /// The initial user to display. /// If set to true, hover/click sounds will play and clicking the avatar will open the user's profile. + /// If set to true, the user status panel will be displayed in the tooltip. /// Whether to show a default guest representation on null user (as opposed to nothing). - public UpdateableAvatar(APIUser? user = null, bool isInteractive = true, bool showGuestOnNull = true) + public UpdateableAvatar(APIUser? user = null, bool isInteractive = true, bool showUserPanel = true, bool showGuestOnNull = true) { this.isInteractive = isInteractive; this.showGuestOnNull = showGuestOnNull; + this.showUserPanel = showUserPanel; User = user; } From a01f6187f4738f85376cb820315d95d8c4545e4c Mon Sep 17 00:00:00 2001 From: Joshua Hegedus Date: Mon, 6 Nov 2023 14:52:06 +0100 Subject: [PATCH 08/20] testing the tooltip --- .../Online/TestSceneUserClickableAvatar.cs | 134 +++++++++--------- osu.Game/Users/Drawables/ClickableAvatar.cs | 43 +++++- osu.Game/Users/Drawables/UpdateableAvatar.cs | 1 + 3 files changed, 102 insertions(+), 76 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs index 72870a5647..678767f15e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs @@ -1,13 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; using NUnit.Framework; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; -using osu.Framework.Testing; using osu.Game.Online.API.Requests.Responses; using osu.Game.Users; using osu.Game.Users.Drawables; @@ -29,12 +27,9 @@ namespace osu.Game.Tests.Visual.Online Spacing = new Vector2(10f), Children = new[] { - generateUser(@"peppy", 2, CountryCode.AU, @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", "99EB47"), - generateUser(@"flyte", 3103765, CountryCode.JP, @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"), - generateUser(@"flyte", 3103765, CountryCode.JP, @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"), - new ClickableAvatar(), - new UpdateableAvatar(), - new UpdateableAvatar(), + generateUser(@"peppy", 2, CountryCode.AU, @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", false, "99EB47"), + generateUser(@"flyte", 3103765, CountryCode.JP, @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg", false), + generateUser(@"joshika39", 17032217, CountryCode.RS, @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", true), }, }; }); @@ -42,68 +37,68 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestClickableAvatarHover() { - AddStep($"click {1}. {nameof(ClickableAvatar)}", () => - { - var targets = this.ChildrenOfType().ToList(); - if (targets.Count < 1) - return; - - InputManager.MoveMouseTo(targets[0]); - }); - AddWaitStep("wait for tooltip to show", 5); - AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - AddWaitStep("wait for tooltip to hide", 3); - - AddStep($"click {2}. {nameof(ClickableAvatar)}", () => - { - var targets = this.ChildrenOfType().ToList(); - if (targets.Count < 2) - return; - - InputManager.MoveMouseTo(targets[1]); - }); - AddWaitStep("wait for tooltip to show", 5); - AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - AddWaitStep("wait for tooltip to hide", 3); - - AddStep($"click {3}. {nameof(ClickableAvatar)}", () => - { - var targets = this.ChildrenOfType().ToList(); - if (targets.Count < 3) - return; - - InputManager.MoveMouseTo(targets[2]); - }); - AddWaitStep("wait for tooltip to show", 5); - AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - AddWaitStep("wait for tooltip to hide", 3); - - AddStep($"click null user {4}. {nameof(ClickableAvatar)}", () => - { - var targets = this.ChildrenOfType().ToList(); - if (targets.Count < 4) - return; - - InputManager.MoveMouseTo(targets[3]); - }); - AddWaitStep("wait for tooltip to show", 5); - AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - AddWaitStep("wait for tooltip to hide", 3); - - AddStep($"click null user {5}. {nameof(ClickableAvatar)}", () => - { - var targets = this.ChildrenOfType().ToList(); - if (targets.Count < 5) - return; - - InputManager.MoveMouseTo(targets[4]); - }); - AddWaitStep("wait for tooltip to show", 5); - AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - AddWaitStep("wait for tooltip to hide", 3); + // AddStep($"click {1}. {nameof(ClickableAvatar)}", () => + // { + // var targets = this.ChildrenOfType().ToList(); + // if (targets.Count < 1) + // return; + // + // InputManager.MoveMouseTo(targets[0]); + // }); + // AddWaitStep("wait for tooltip to show", 5); + // AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + // AddWaitStep("wait for tooltip to hide", 3); + // + // AddStep($"click {2}. {nameof(ClickableAvatar)}", () => + // { + // var targets = this.ChildrenOfType().ToList(); + // if (targets.Count < 2) + // return; + // + // InputManager.MoveMouseTo(targets[1]); + // }); + // AddWaitStep("wait for tooltip to show", 5); + // AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + // AddWaitStep("wait for tooltip to hide", 3); + // + // AddStep($"click {3}. {nameof(ClickableAvatar)}", () => + // { + // var targets = this.ChildrenOfType().ToList(); + // if (targets.Count < 3) + // return; + // + // InputManager.MoveMouseTo(targets[2]); + // }); + // AddWaitStep("wait for tooltip to show", 5); + // AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + // AddWaitStep("wait for tooltip to hide", 3); + // + // AddStep($"click null user {4}. {nameof(ClickableAvatar)}", () => + // { + // var targets = this.ChildrenOfType().ToList(); + // if (targets.Count < 4) + // return; + // + // InputManager.MoveMouseTo(targets[3]); + // }); + // AddWaitStep("wait for tooltip to show", 5); + // AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + // AddWaitStep("wait for tooltip to hide", 3); + // + // AddStep($"click null user {5}. {nameof(ClickableAvatar)}", () => + // { + // var targets = this.ChildrenOfType().ToList(); + // if (targets.Count < 5) + // return; + // + // InputManager.MoveMouseTo(targets[4]); + // }); + // AddWaitStep("wait for tooltip to show", 5); + // AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + // AddWaitStep("wait for tooltip to hide", 3); } - private Drawable generateUser(string username, int id, CountryCode countryCode, string cover, string? color = null) + private Drawable generateUser(string username, int id, CountryCode countryCode, string cover, bool isTooltipEnabled, string? color = null) { return new ClickableAvatar(new APIUser { @@ -115,7 +110,7 @@ namespace osu.Game.Tests.Visual.Online Status = { Value = new UserStatusOnline() - } + }, }) { Width = 50, @@ -126,6 +121,7 @@ namespace osu.Game.Tests.Visual.Online { Type = EdgeEffectType.Shadow, Radius = 1, Colour = Color4.Black.Opacity(0.2f), }, + IsTooltipEnabled = isTooltipEnabled, }; } } diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 0520f62665..c11ad7f720 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -1,12 +1,15 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Game.Graphics.Containers; +using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; using osuTK; @@ -14,14 +17,32 @@ namespace osu.Game.Users.Drawables { public partial class ClickableAvatar : OsuClickableContainer, IHasCustomTooltip { - public ITooltip GetCustomTooltip() => new UserGridPanelTooltip(IsTooltipEnabled); + public ITooltip GetCustomTooltip() => new UserGridPanelTooltip(this); public UserGridPanel TooltipContent => new UserGridPanel(user!) { Width = 300 }; - public bool IsTooltipEnabled; + public override LocalisableString TooltipText + { + get + { + if (!Enabled.Value) + return string.Empty; + + return !IsTooltipEnabled ? (user?.Username ?? string.Empty) : ContextMenuStrings.ViewProfile; + } + set => throw new NotSupportedException(); + } + + /// + /// By default, the tooltip will show "view profile" as avatars are usually displayed next to a username. + /// Setting this to true exposes the username via tooltip for special cases where this is not true. + /// + // public bool ShowUsernameTooltip { get; set; } + + public bool IsTooltipEnabled { get; set; } private readonly APIUser? user; @@ -35,12 +56,16 @@ namespace osu.Game.Users.Drawables public ClickableAvatar(APIUser? user = null) { this.user = user; - IsTooltipEnabled = true; if (user?.Id != APIUser.SYSTEM_USER_ID) Action = openProfile; } + public void SetValue(out bool value) + { + value = IsTooltipEnabled; + } + [BackgroundDependencyLoader] private void load() { @@ -61,18 +86,22 @@ namespace osu.Game.Users.Drawables return base.OnClick(e); } - private partial class UserGridPanelTooltip : VisibilityContainer, ITooltip + public partial class UserGridPanelTooltip : VisibilityContainer, ITooltip { - private readonly bool isEnabled; + private readonly ClickableAvatar parent; private UserGridPanel? displayedUser; + private bool isEnabled; - public UserGridPanelTooltip(bool isEnabled = true) + public UserGridPanelTooltip(ClickableAvatar parent) { - this.isEnabled = isEnabled; + this.parent = parent ?? throw new ArgumentNullException(nameof(parent)); + isEnabled = this.parent.IsTooltipEnabled; } protected override void PopIn() { + parent.SetValue(out isEnabled); + if (displayedUser is null || !isEnabled) { return; diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index a970997056..64d64c56ce 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -75,6 +75,7 @@ namespace osu.Game.Users.Drawables return new ClickableAvatar(user) { RelativeSizeAxes = Axes.Both, + IsTooltipEnabled = showUserPanel }; } else From f897c21b3f5b57b5892f25cef3644aabf82d7c43 Mon Sep 17 00:00:00 2001 From: Joshua Hegedus Date: Mon, 6 Nov 2023 15:25:12 +0100 Subject: [PATCH 09/20] partial change --- osu.Game/Users/Drawables/ClickableAvatar.cs | 39 ++++++++------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index c11ad7f720..376ce0b821 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -15,14 +15,14 @@ using osuTK; namespace osu.Game.Users.Drawables { - public partial class ClickableAvatar : OsuClickableContainer, IHasCustomTooltip + public partial class ClickableAvatar : OsuClickableContainer, IHasCustomTooltip { - public ITooltip GetCustomTooltip() => new UserGridPanelTooltip(this); - - public UserGridPanel TooltipContent => new UserGridPanel(user!) + public ITooltip GetCustomTooltip() { - Width = 300 - }; + return new APIUserTooltip(user); + } + + public APIUser? TooltipContent => user; public override LocalisableString TooltipText { @@ -36,12 +36,6 @@ namespace osu.Game.Users.Drawables set => throw new NotSupportedException(); } - /// - /// By default, the tooltip will show "view profile" as avatars are usually displayed next to a username. - /// Setting this to true exposes the username via tooltip for special cases where this is not true. - /// - // public bool ShowUsernameTooltip { get; set; } - public bool IsTooltipEnabled { get; set; } private readonly APIUser? user; @@ -86,28 +80,23 @@ namespace osu.Game.Users.Drawables return base.OnClick(e); } - public partial class UserGridPanelTooltip : VisibilityContainer, ITooltip + public partial class APIUserTooltip : VisibilityContainer, ITooltip { - private readonly ClickableAvatar parent; - private UserGridPanel? displayedUser; - private bool isEnabled; + private APIUser? user; - public UserGridPanelTooltip(ClickableAvatar parent) + public APIUserTooltip(APIUser? user) { - this.parent = parent ?? throw new ArgumentNullException(nameof(parent)); - isEnabled = this.parent.IsTooltipEnabled; + this.user = user; } protected override void PopIn() { - parent.SetValue(out isEnabled); - - if (displayedUser is null || !isEnabled) + if (user is null) { return; } - Child = displayedUser; + Child = new UserGridPanel(user); this.FadeIn(20, Easing.OutQuint); } @@ -115,9 +104,9 @@ namespace osu.Game.Users.Drawables public void Move(Vector2 pos) => Position = pos; - public void SetContent(UserGridPanel userGridPanel) + public void SetContent(APIUser user) { - displayedUser = userGridPanel; + this.user = user; } } } From ccb9ff826a87dbafbbeb0a0a572a404bc88c7e88 Mon Sep 17 00:00:00 2001 From: Joshua Hegedus Date: Thu, 9 Nov 2023 13:09:59 +0100 Subject: [PATCH 10/20] fixed tests --- .../Online/TestSceneUserClickableAvatar.cs | 130 +++++++++--------- .../OnlinePlay/Components/ParticipantsList.cs | 2 +- .../DrawableRoomParticipantsList.cs | 2 +- osu.Game/Users/Drawables/ClickableAvatar.cs | 115 +++++++++++----- osu.Game/Users/Drawables/UpdateableAvatar.cs | 9 +- 5 files changed, 152 insertions(+), 106 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs index 678767f15e..9217104aa8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs @@ -1,11 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using NUnit.Framework; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; +using osu.Framework.Testing; using osu.Game.Online.API.Requests.Responses; using osu.Game.Users; using osu.Game.Users.Drawables; @@ -28,8 +30,10 @@ namespace osu.Game.Tests.Visual.Online Children = new[] { generateUser(@"peppy", 2, CountryCode.AU, @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", false, "99EB47"), - generateUser(@"flyte", 3103765, CountryCode.JP, @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg", false), - generateUser(@"joshika39", 17032217, CountryCode.RS, @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", true), + generateUser(@"flyte", 3103765, CountryCode.JP, @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg", true), + generateUser(@"joshika39", 17032217, CountryCode.RS, @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", false), + new UpdateableAvatar(), + new UpdateableAvatar() }, }; }); @@ -37,68 +41,68 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestClickableAvatarHover() { - // AddStep($"click {1}. {nameof(ClickableAvatar)}", () => - // { - // var targets = this.ChildrenOfType().ToList(); - // if (targets.Count < 1) - // return; - // - // InputManager.MoveMouseTo(targets[0]); - // }); - // AddWaitStep("wait for tooltip to show", 5); - // AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - // AddWaitStep("wait for tooltip to hide", 3); - // - // AddStep($"click {2}. {nameof(ClickableAvatar)}", () => - // { - // var targets = this.ChildrenOfType().ToList(); - // if (targets.Count < 2) - // return; - // - // InputManager.MoveMouseTo(targets[1]); - // }); - // AddWaitStep("wait for tooltip to show", 5); - // AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - // AddWaitStep("wait for tooltip to hide", 3); - // - // AddStep($"click {3}. {nameof(ClickableAvatar)}", () => - // { - // var targets = this.ChildrenOfType().ToList(); - // if (targets.Count < 3) - // return; - // - // InputManager.MoveMouseTo(targets[2]); - // }); - // AddWaitStep("wait for tooltip to show", 5); - // AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - // AddWaitStep("wait for tooltip to hide", 3); - // - // AddStep($"click null user {4}. {nameof(ClickableAvatar)}", () => - // { - // var targets = this.ChildrenOfType().ToList(); - // if (targets.Count < 4) - // return; - // - // InputManager.MoveMouseTo(targets[3]); - // }); - // AddWaitStep("wait for tooltip to show", 5); - // AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - // AddWaitStep("wait for tooltip to hide", 3); - // - // AddStep($"click null user {5}. {nameof(ClickableAvatar)}", () => - // { - // var targets = this.ChildrenOfType().ToList(); - // if (targets.Count < 5) - // return; - // - // InputManager.MoveMouseTo(targets[4]); - // }); - // AddWaitStep("wait for tooltip to show", 5); - // AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - // AddWaitStep("wait for tooltip to hide", 3); + AddStep($"click user {1} with UserGridPanel {nameof(ClickableAvatar)}", () => + { + var targets = this.ChildrenOfType().ToList(); + if (targets.Count < 1) + return; + + InputManager.MoveMouseTo(targets[0]); + }); + AddWaitStep("wait for tooltip to show", 5); + AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + AddWaitStep("wait for tooltip to hide", 3); + + AddStep($"click user {2} with username only. {nameof(ClickableAvatar)}", () => + { + var targets = this.ChildrenOfType().ToList(); + if (targets.Count < 2) + return; + + InputManager.MoveMouseTo(targets[1]); + }); + AddWaitStep("wait for tooltip to show", 5); + AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + AddWaitStep("wait for tooltip to hide", 3); + + AddStep($"click user {3} with UserGridPanel {nameof(ClickableAvatar)}", () => + { + var targets = this.ChildrenOfType().ToList(); + if (targets.Count < 3) + return; + + InputManager.MoveMouseTo(targets[2]); + }); + AddWaitStep("wait for tooltip to show", 5); + AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + AddWaitStep("wait for tooltip to hide", 3); + + AddStep($"click null user {4}. {nameof(ClickableAvatar)}", () => + { + var targets = this.ChildrenOfType().ToList(); + if (targets.Count < 4) + return; + + InputManager.MoveMouseTo(targets[3]); + }); + AddWaitStep("wait for tooltip to show", 5); + AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + AddWaitStep("wait for tooltip to hide", 3); + + AddStep($"click null user {5}. {nameof(ClickableAvatar)}", () => + { + var targets = this.ChildrenOfType().ToList(); + if (targets.Count < 5) + return; + + InputManager.MoveMouseTo(targets[4]); + }); + AddWaitStep("wait for tooltip to show", 5); + AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + AddWaitStep("wait for tooltip to hide", 3); } - private Drawable generateUser(string username, int id, CountryCode countryCode, string cover, bool isTooltipEnabled, string? color = null) + private Drawable generateUser(string username, int id, CountryCode countryCode, string cover, bool onlyUsername, string? color = null) { return new ClickableAvatar(new APIUser { @@ -121,7 +125,7 @@ namespace osu.Game.Tests.Visual.Online { Type = EdgeEffectType.Shadow, Radius = 1, Colour = Color4.Black.Opacity(0.2f), }, - IsTooltipEnabled = isTooltipEnabled, + ShowUsernameOnly = onlyUsername, }; } } diff --git a/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs index cb1a846d6c..8cde7859b2 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs @@ -115,7 +115,7 @@ namespace osu.Game.Screens.OnlinePlay.Components RelativeSizeAxes = Axes.Both, Colour = Color4Extensions.FromHex(@"27252d"), }, - avatar = new UpdateableAvatar { RelativeSizeAxes = Axes.Both }, + avatar = new UpdateableAvatar(showUsernameOnly: true) { RelativeSizeAxes = Axes.Both }, }; } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs index 1814f5359f..65f0555612 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs @@ -289,7 +289,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components set => avatar.User = value; } - private readonly UpdateableAvatar avatar = new UpdateableAvatar { RelativeSizeAxes = Axes.Both }; + private readonly UpdateableAvatar avatar = new UpdateableAvatar(showUsernameOnly: true) { RelativeSizeAxes = Axes.Both }; [BackgroundDependencyLoader] private void load(OverlayColourProvider colours) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 376ce0b821..e7934016bc 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -1,44 +1,43 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics.Containers; -using osu.Game.Localisation; +using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osuTK; +using osuTK.Graphics; namespace osu.Game.Users.Drawables { - public partial class ClickableAvatar : OsuClickableContainer, IHasCustomTooltip + public partial class ClickableAvatar : OsuClickableContainer, IHasCustomTooltip { - public ITooltip GetCustomTooltip() - { - return new APIUserTooltip(user); - } + // public ITooltip GetCustomTooltip() => new APIUserTooltip(user!) { ShowTooltip = TooltipEnabled }; + public ITooltip GetCustomTooltip() => new APIUserTooltip(new APIUserTooltipContent(user!)); - public APIUser? TooltipContent => user; - - public override LocalisableString TooltipText - { - get - { - if (!Enabled.Value) - return string.Empty; - - return !IsTooltipEnabled ? (user?.Username ?? string.Empty) : ContextMenuStrings.ViewProfile; - } - set => throw new NotSupportedException(); - } - - public bool IsTooltipEnabled { get; set; } + public APIUserTooltipContent TooltipContent => content; + private readonly APIUserTooltipContent content; private readonly APIUser? user; + private bool tooltipEnabled; + + public override LocalisableString TooltipText => user!.Username; + + public bool ShowUsernameOnly + { + get => tooltipEnabled; + set + { + tooltipEnabled = value; + content.ShowUsernameOnly = ShowUsernameOnly; + } + } [Resolved] private OsuGame? game { get; set; } @@ -53,11 +52,8 @@ namespace osu.Game.Users.Drawables if (user?.Id != APIUser.SYSTEM_USER_ID) Action = openProfile; - } - public void SetValue(out bool value) - { - value = IsTooltipEnabled; + content = new APIUserTooltipContent(user!, ShowUsernameOnly); } [BackgroundDependencyLoader] @@ -80,23 +76,57 @@ namespace osu.Game.Users.Drawables return base.OnClick(e); } - public partial class APIUserTooltip : VisibilityContainer, ITooltip + public partial class APIUserTooltip : VisibilityContainer, ITooltip { - private APIUser? user; - - public APIUserTooltip(APIUser? user) + private OsuSpriteText text; + private APIUserTooltipContent content; + public APIUserTooltip(APIUserTooltipContent content) { - this.user = user; + this.content = content; + AutoSizeAxes = Axes.Both; + Masking = true; + CornerRadius = 5; + + Child = new UserGridPanel(content.User) + { + Width = 300 + }; + text = new OsuSpriteText() + { + Text = this.content.User.Username + }; } protected override void PopIn() { - if (user is null) + if (content.ShowUsernameOnly) { - return; + Child = new UserGridPanel(content.User) + { + Width = 300 + }; + } + else + { + Alpha = 0; + AutoSizeAxes = Axes.Both; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Gray, + }, + text = new OsuSpriteText() + { + Font = FrameworkFont.Regular.With(size: 16), + Padding = new MarginPadding(5), + Text = content.User.Username + } + }; } - Child = new UserGridPanel(user); this.FadeIn(20, Easing.OutQuint); } @@ -104,9 +134,22 @@ namespace osu.Game.Users.Drawables public void Move(Vector2 pos) => Position = pos; - public void SetContent(APIUser user) + public void SetContent(APIUserTooltipContent content) { - this.user = user; + this.content = content; + text.Text = this.content.User.Username; + } + } + + public class APIUserTooltipContent + { + public APIUser User { get; } + public bool ShowUsernameOnly { get; set; } + + public APIUserTooltipContent(APIUser user, bool showUsernameOnly = false) + { + User = user; + ShowUsernameOnly = showUsernameOnly; } } } diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index 64d64c56ce..f6363f61e6 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -47,20 +47,20 @@ namespace osu.Game.Users.Drawables private readonly bool isInteractive; private readonly bool showGuestOnNull; - private readonly bool showUserPanel; + private readonly bool showUsernameOnly; /// /// Construct a new UpdateableAvatar. /// /// The initial user to display. /// If set to true, hover/click sounds will play and clicking the avatar will open the user's profile. - /// If set to true, the user status panel will be displayed in the tooltip. + /// If set to true, the user status panel will be displayed in the tooltip. /// Whether to show a default guest representation on null user (as opposed to nothing). - public UpdateableAvatar(APIUser? user = null, bool isInteractive = true, bool showUserPanel = true, bool showGuestOnNull = true) + public UpdateableAvatar(APIUser? user = null, bool isInteractive = true, bool showUsernameOnly = false, bool showGuestOnNull = true) { this.isInteractive = isInteractive; this.showGuestOnNull = showGuestOnNull; - this.showUserPanel = showUserPanel; + this.showUsernameOnly = showUsernameOnly; User = user; } @@ -75,7 +75,6 @@ namespace osu.Game.Users.Drawables return new ClickableAvatar(user) { RelativeSizeAxes = Axes.Both, - IsTooltipEnabled = showUserPanel }; } else From 4900a91c60fda24f76aeba4d2d2bf42cc1929e2d Mon Sep 17 00:00:00 2001 From: Joshua Hegedus Date: Thu, 9 Nov 2023 13:27:09 +0100 Subject: [PATCH 11/20] fixed static analysis problems and finished the implementation --- .../Online/TestSceneUserClickableAvatar.cs | 40 +++++++++---------- osu.Game/Users/Drawables/ClickableAvatar.cs | 12 +++--- osu.Game/Users/Drawables/UpdateableAvatar.cs | 11 +++-- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs index 9217104aa8..50e5653ad5 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs @@ -105,28 +105,28 @@ namespace osu.Game.Tests.Visual.Online private Drawable generateUser(string username, int id, CountryCode countryCode, string cover, bool onlyUsername, string? color = null) { return new ClickableAvatar(new APIUser + { + Username = username, + Id = id, + CountryCode = countryCode, + CoverUrl = cover, + Colour = color ?? "000000", + Status = { - Username = username, - Id = id, - CountryCode = countryCode, - CoverUrl = cover, - Colour = color ?? "000000", - Status = - { - Value = new UserStatusOnline() - }, - }) + Value = new UserStatusOnline() + }, + }) + { + Width = 50, + Height = 50, + CornerRadius = 10, + Masking = true, + EdgeEffect = new EdgeEffectParameters { - Width = 50, - Height = 50, - CornerRadius = 10, - Masking = true, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, Radius = 1, Colour = Color4.Black.Opacity(0.2f), - }, - ShowUsernameOnly = onlyUsername, - }; + Type = EdgeEffectType.Shadow, Radius = 1, Colour = Color4.Black.Opacity(0.2f), + }, + ShowUsernameOnly = onlyUsername, + }; } } } diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index e7934016bc..de0bcad497 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -21,9 +21,8 @@ namespace osu.Game.Users.Drawables // public ITooltip GetCustomTooltip() => new APIUserTooltip(user!) { ShowTooltip = TooltipEnabled }; public ITooltip GetCustomTooltip() => new APIUserTooltip(new APIUserTooltipContent(user!)); - public APIUserTooltipContent TooltipContent => content; + public APIUserTooltipContent TooltipContent { get; } - private readonly APIUserTooltipContent content; private readonly APIUser? user; private bool tooltipEnabled; @@ -35,7 +34,7 @@ namespace osu.Game.Users.Drawables set { tooltipEnabled = value; - content.ShowUsernameOnly = ShowUsernameOnly; + TooltipContent.ShowUsernameOnly = ShowUsernameOnly; } } @@ -53,7 +52,7 @@ namespace osu.Game.Users.Drawables if (user?.Id != APIUser.SYSTEM_USER_ID) Action = openProfile; - content = new APIUserTooltipContent(user!, ShowUsernameOnly); + TooltipContent = new APIUserTooltipContent(user!, ShowUsernameOnly); } [BackgroundDependencyLoader] @@ -80,6 +79,7 @@ namespace osu.Game.Users.Drawables { private OsuSpriteText text; private APIUserTooltipContent content; + public APIUserTooltip(APIUserTooltipContent content) { this.content = content; @@ -91,7 +91,7 @@ namespace osu.Game.Users.Drawables { Width = 300 }; - text = new OsuSpriteText() + text = new OsuSpriteText { Text = this.content.User.Username }; @@ -118,7 +118,7 @@ namespace osu.Game.Users.Drawables RelativeSizeAxes = Axes.Both, Colour = Color4.Gray, }, - text = new OsuSpriteText() + text = new OsuSpriteText { Font = FrameworkFont.Regular.With(size: 16), Padding = new MarginPadding(5), diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index f6363f61e6..f220ee5a25 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -75,15 +75,14 @@ namespace osu.Game.Users.Drawables return new ClickableAvatar(user) { RelativeSizeAxes = Axes.Both, + ShowUsernameOnly = showUsernameOnly }; } - else + + return new DrawableAvatar(user) { - return new DrawableAvatar(user) - { - RelativeSizeAxes = Axes.Both, - }; - } + RelativeSizeAxes = Axes.Both, + }; } } } From 615d8384abcc3c412a831a70a73ed0f6c6173467 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Nov 2023 22:27:29 +0900 Subject: [PATCH 12/20] Refactor everythign back to sanity --- .../Cards/Statistics/BeatmapCardStatistic.cs | 2 +- osu.Game/Users/Drawables/ClickableAvatar.cs | 93 +++---------------- 2 files changed, 13 insertions(+), 82 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardStatistic.cs index 10de2b9128..6fd7142c05 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardStatistic.cs @@ -74,7 +74,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Statistics #region Tooltip implementation - public virtual ITooltip GetCustomTooltip() => null; + public virtual ITooltip GetCustomTooltip() => null!; public virtual object TooltipContent => null; #endregion diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index de0bcad497..48a12acb5e 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -5,38 +5,25 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; -using osu.Framework.Localisation; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; +using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osuTK; -using osuTK.Graphics; namespace osu.Game.Users.Drawables { - public partial class ClickableAvatar : OsuClickableContainer, IHasCustomTooltip + public partial class ClickableAvatar : OsuClickableContainer, IHasCustomTooltip { // public ITooltip GetCustomTooltip() => new APIUserTooltip(user!) { ShowTooltip = TooltipEnabled }; - public ITooltip GetCustomTooltip() => new APIUserTooltip(new APIUserTooltipContent(user!)); + public ITooltip GetCustomTooltip() => new UserCardTooltip(); - public APIUserTooltipContent TooltipContent { get; } + public APIUser? TooltipContent { get; } private readonly APIUser? user; - private bool tooltipEnabled; - public override LocalisableString TooltipText => user!.Username; - - public bool ShowUsernameOnly - { - get => tooltipEnabled; - set - { - tooltipEnabled = value; - TooltipContent.ShowUsernameOnly = ShowUsernameOnly; - } - } + // TODO: reimplement. + public bool ShowUsernameOnly { get; set; } [Resolved] private OsuGame? game { get; set; } @@ -47,12 +34,10 @@ namespace osu.Game.Users.Drawables /// The user. A null value will get a placeholder avatar. public ClickableAvatar(APIUser? user = null) { - this.user = user; - if (user?.Id != APIUser.SYSTEM_USER_ID) Action = openProfile; - TooltipContent = new APIUserTooltipContent(user!, ShowUsernameOnly); + TooltipContent = this.user = user; } [BackgroundDependencyLoader] @@ -75,58 +60,17 @@ namespace osu.Game.Users.Drawables return base.OnClick(e); } - public partial class APIUserTooltip : VisibilityContainer, ITooltip + public partial class UserCardTooltip : VisibilityContainer, ITooltip { - private OsuSpriteText text; - private APIUserTooltipContent content; - - public APIUserTooltip(APIUserTooltipContent content) + public UserCardTooltip() { - this.content = content; AutoSizeAxes = Axes.Both; Masking = true; CornerRadius = 5; - - Child = new UserGridPanel(content.User) - { - Width = 300 - }; - text = new OsuSpriteText - { - Text = this.content.User.Username - }; } protected override void PopIn() { - if (content.ShowUsernameOnly) - { - Child = new UserGridPanel(content.User) - { - Width = 300 - }; - } - else - { - Alpha = 0; - AutoSizeAxes = Axes.Both; - - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Gray, - }, - text = new OsuSpriteText - { - Font = FrameworkFont.Regular.With(size: 16), - Padding = new MarginPadding(5), - Text = content.User.Username - } - }; - } - this.FadeIn(20, Easing.OutQuint); } @@ -134,23 +78,10 @@ namespace osu.Game.Users.Drawables public void Move(Vector2 pos) => Position = pos; - public void SetContent(APIUserTooltipContent content) + public void SetContent(APIUser? content) => LoadComponentAsync(new UserGridPanel(content ?? new GuestUser()) { - this.content = content; - text.Text = this.content.User.Username; - } - } - - public class APIUserTooltipContent - { - public APIUser User { get; } - public bool ShowUsernameOnly { get; set; } - - public APIUserTooltipContent(APIUser user, bool showUsernameOnly = false) - { - User = user; - ShowUsernameOnly = showUsernameOnly; - } + Width = 300, + }, panel => Child = panel); } } } From 7fc2050f7227424b7e734260126146c48e99358e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Nov 2023 11:52:34 +0900 Subject: [PATCH 13/20] Rename variables and mak seconary tooltip type work again --- .../Online/TestSceneUserClickableAvatar.cs | 9 ++- .../OnlinePlay/Components/ParticipantsList.cs | 2 +- .../DrawableRoomParticipantsList.cs | 2 +- osu.Game/Users/Drawables/ClickableAvatar.cs | 74 ++++++++++++++----- osu.Game/Users/Drawables/UpdateableAvatar.cs | 11 ++- 5 files changed, 69 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs index 50e5653ad5..93e2583eb7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs @@ -102,9 +102,9 @@ namespace osu.Game.Tests.Visual.Online AddWaitStep("wait for tooltip to hide", 3); } - private Drawable generateUser(string username, int id, CountryCode countryCode, string cover, bool onlyUsername, string? color = null) + private Drawable generateUser(string username, int id, CountryCode countryCode, string cover, bool showPanel, string? color = null) { - return new ClickableAvatar(new APIUser + var user = new APIUser { Username = username, Id = id, @@ -115,7 +115,9 @@ namespace osu.Game.Tests.Visual.Online { Value = new UserStatusOnline() }, - }) + }; + + return new ClickableAvatar(user, showPanel) { Width = 50, Height = 50, @@ -125,7 +127,6 @@ namespace osu.Game.Tests.Visual.Online { Type = EdgeEffectType.Shadow, Radius = 1, Colour = Color4.Black.Opacity(0.2f), }, - ShowUsernameOnly = onlyUsername, }; } } diff --git a/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs index 8cde7859b2..c4aefe4f99 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs @@ -115,7 +115,7 @@ namespace osu.Game.Screens.OnlinePlay.Components RelativeSizeAxes = Axes.Both, Colour = Color4Extensions.FromHex(@"27252d"), }, - avatar = new UpdateableAvatar(showUsernameOnly: true) { RelativeSizeAxes = Axes.Both }, + avatar = new UpdateableAvatar(showUserPanelOnHover: true) { RelativeSizeAxes = Axes.Both }, }; } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs index 65f0555612..60e05285d9 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs @@ -289,7 +289,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components set => avatar.User = value; } - private readonly UpdateableAvatar avatar = new UpdateableAvatar(showUsernameOnly: true) { RelativeSizeAxes = Axes.Both }; + private readonly UpdateableAvatar avatar = new UpdateableAvatar(showUserPanelOnHover: true) { RelativeSizeAxes = Axes.Both }; [BackgroundDependencyLoader] private void load(OverlayColourProvider colours) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 48a12acb5e..6390acc608 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -1,12 +1,15 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Cursor; +using osu.Game.Localisation; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osuTK; @@ -15,15 +18,13 @@ namespace osu.Game.Users.Drawables { public partial class ClickableAvatar : OsuClickableContainer, IHasCustomTooltip { - // public ITooltip GetCustomTooltip() => new APIUserTooltip(user!) { ShowTooltip = TooltipEnabled }; - public ITooltip GetCustomTooltip() => new UserCardTooltip(); + public ITooltip GetCustomTooltip() => showCardOnHover ? new UserCardTooltip() : new NoCardTooltip(); public APIUser? TooltipContent { get; } private readonly APIUser? user; - // TODO: reimplement. - public bool ShowUsernameOnly { get; set; } + private readonly bool showCardOnHover; [Resolved] private OsuGame? game { get; set; } @@ -32,12 +33,15 @@ namespace osu.Game.Users.Drawables /// A clickable avatar for the specified user, with UI sounds included. /// /// The user. A null value will get a placeholder avatar. - public ClickableAvatar(APIUser? user = null) + /// + public ClickableAvatar(APIUser? user = null, bool showCardOnHover = false) { if (user?.Id != APIUser.SYSTEM_USER_ID) Action = openProfile; - TooltipContent = this.user = user; + this.showCardOnHover = showCardOnHover; + + TooltipContent = this.user = user ?? new GuestUser(); } [BackgroundDependencyLoader] @@ -65,23 +69,59 @@ namespace osu.Game.Users.Drawables public UserCardTooltip() { AutoSizeAxes = Axes.Both; - Masking = true; - CornerRadius = 5; } - protected override void PopIn() - { - this.FadeIn(20, Easing.OutQuint); - } - - protected override void PopOut() => this.FadeOut(80, Easing.OutQuint); + protected override void PopIn() => this.FadeIn(150, Easing.OutQuint); + protected override void PopOut() => this.Delay(150).FadeOut(500, Easing.OutQuint); public void Move(Vector2 pos) => Position = pos; - public void SetContent(APIUser? content) => LoadComponentAsync(new UserGridPanel(content ?? new GuestUser()) + private APIUser? user; + + public void SetContent(APIUser? content) { - Width = 300, - }, panel => Child = panel); + if (content == user && Children.Any()) + return; + + user = content; + + if (user != null) + { + LoadComponentAsync(new UserGridPanel(user) + { + Width = 300, + }, panel => Child = panel); + } + else + { + var tooltip = new OsuTooltipContainer.OsuTooltip(); + tooltip.SetContent(ContextMenuStrings.ViewProfile); + tooltip.Show(); + + Child = tooltip; + } + } + } + + public partial class NoCardTooltip : VisibilityContainer, ITooltip + { + public NoCardTooltip() + { + var tooltip = new OsuTooltipContainer.OsuTooltip(); + tooltip.SetContent(ContextMenuStrings.ViewProfile); + tooltip.Show(); + + Child = tooltip; + } + + protected override void PopIn() => this.FadeIn(150, Easing.OutQuint); + protected override void PopOut() => this.Delay(150).FadeOut(500, Easing.OutQuint); + + public void Move(Vector2 pos) => Position = pos; + + public void SetContent(APIUser? content) + { + } } } } diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index f220ee5a25..b020e7fa63 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -47,20 +47,20 @@ namespace osu.Game.Users.Drawables private readonly bool isInteractive; private readonly bool showGuestOnNull; - private readonly bool showUsernameOnly; + private readonly bool showUserPanelOnHover; /// /// Construct a new UpdateableAvatar. /// /// The initial user to display. /// If set to true, hover/click sounds will play and clicking the avatar will open the user's profile. - /// If set to true, the user status panel will be displayed in the tooltip. + /// If set to true, the user status panel will be displayed in the tooltip. /// Whether to show a default guest representation on null user (as opposed to nothing). - public UpdateableAvatar(APIUser? user = null, bool isInteractive = true, bool showUsernameOnly = false, bool showGuestOnNull = true) + public UpdateableAvatar(APIUser? user = null, bool isInteractive = true, bool showUserPanelOnHover = false, bool showGuestOnNull = true) { this.isInteractive = isInteractive; this.showGuestOnNull = showGuestOnNull; - this.showUsernameOnly = showUsernameOnly; + this.showUserPanelOnHover = showUserPanelOnHover; User = user; } @@ -72,10 +72,9 @@ namespace osu.Game.Users.Drawables if (isInteractive) { - return new ClickableAvatar(user) + return new ClickableAvatar(user, showUserPanelOnHover) { RelativeSizeAxes = Axes.Both, - ShowUsernameOnly = showUsernameOnly }; } From d0f1326a63da2187c80c7429cf386bfb3856c8c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 10 Nov 2023 17:54:48 +0900 Subject: [PATCH 14/20] Fix formatting --- osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs index 93e2583eb7..b38fb9153a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs @@ -125,7 +125,9 @@ namespace osu.Game.Tests.Visual.Online Masking = true, EdgeEffect = new EdgeEffectParameters { - Type = EdgeEffectType.Shadow, Radius = 1, Colour = Color4.Black.Opacity(0.2f), + Type = EdgeEffectType.Shadow, + Radius = 1, + Colour = Color4.Black.Opacity(0.2f), }, }; } From 36d0bae42dfe95481b3e20751d8f7032b925e9df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 10 Nov 2023 17:57:16 +0900 Subject: [PATCH 15/20] Restore mention of dependency on another ctor param --- osu.Game/Users/Drawables/UpdateableAvatar.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index b020e7fa63..21153ecfc3 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -54,7 +54,10 @@ namespace osu.Game.Users.Drawables /// /// The initial user to display. /// If set to true, hover/click sounds will play and clicking the avatar will open the user's profile. - /// If set to true, the user status panel will be displayed in the tooltip. + /// + /// If set to true, the user status panel will be displayed in the tooltip. + /// Only has an effect if is true. + /// /// Whether to show a default guest representation on null user (as opposed to nothing). public UpdateableAvatar(APIUser? user = null, bool isInteractive = true, bool showUserPanelOnHover = false, bool showGuestOnNull = true) { From fbf94214a536a5b5aa7246d2ee34ee5ecacf8fb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 10 Nov 2023 18:36:09 +0900 Subject: [PATCH 16/20] Fully delegate tooltip show/hide logic --- osu.Game/Users/Drawables/ClickableAvatar.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 6390acc608..ef451df95d 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -105,17 +105,17 @@ namespace osu.Game.Users.Drawables public partial class NoCardTooltip : VisibilityContainer, ITooltip { + private readonly OsuTooltipContainer.OsuTooltip tooltip; + public NoCardTooltip() { - var tooltip = new OsuTooltipContainer.OsuTooltip(); + tooltip = new OsuTooltipContainer.OsuTooltip(); tooltip.SetContent(ContextMenuStrings.ViewProfile); - tooltip.Show(); - Child = tooltip; } - protected override void PopIn() => this.FadeIn(150, Easing.OutQuint); - protected override void PopOut() => this.Delay(150).FadeOut(500, Easing.OutQuint); + protected override void PopIn() => tooltip.Show(); + protected override void PopOut() => tooltip.Hide(); public void Move(Vector2 pos) => Position = pos; From b6dcd7d55f0d421d85e2e97d00ae5704d1fb5487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 10 Nov 2023 18:48:45 +0900 Subject: [PATCH 17/20] Fix tests so that they actually assert something --- .../Online/TestSceneUserClickableAvatar.cs | 67 +++---------------- 1 file changed, 9 insertions(+), 58 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs index b38fb9153a..9edaa841b2 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Testing; +using osu.Game.Graphics.Cursor; using osu.Game.Online.API.Requests.Responses; using osu.Game.Users; using osu.Game.Users.Drawables; @@ -41,65 +42,15 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestClickableAvatarHover() { - AddStep($"click user {1} with UserGridPanel {nameof(ClickableAvatar)}", () => - { - var targets = this.ChildrenOfType().ToList(); - if (targets.Count < 1) - return; + AddStep("hover avatar with user panel", () => InputManager.MoveMouseTo(this.ChildrenOfType().ElementAt(1))); + AddUntilStep("wait for tooltip to show", () => this.ChildrenOfType().FirstOrDefault()?.State.Value == Visibility.Visible); + AddStep("hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + AddUntilStep("wait for tooltip to hide", () => this.ChildrenOfType().FirstOrDefault()?.State.Value == Visibility.Hidden); - InputManager.MoveMouseTo(targets[0]); - }); - AddWaitStep("wait for tooltip to show", 5); - AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - AddWaitStep("wait for tooltip to hide", 3); - - AddStep($"click user {2} with username only. {nameof(ClickableAvatar)}", () => - { - var targets = this.ChildrenOfType().ToList(); - if (targets.Count < 2) - return; - - InputManager.MoveMouseTo(targets[1]); - }); - AddWaitStep("wait for tooltip to show", 5); - AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - AddWaitStep("wait for tooltip to hide", 3); - - AddStep($"click user {3} with UserGridPanel {nameof(ClickableAvatar)}", () => - { - var targets = this.ChildrenOfType().ToList(); - if (targets.Count < 3) - return; - - InputManager.MoveMouseTo(targets[2]); - }); - AddWaitStep("wait for tooltip to show", 5); - AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - AddWaitStep("wait for tooltip to hide", 3); - - AddStep($"click null user {4}. {nameof(ClickableAvatar)}", () => - { - var targets = this.ChildrenOfType().ToList(); - if (targets.Count < 4) - return; - - InputManager.MoveMouseTo(targets[3]); - }); - AddWaitStep("wait for tooltip to show", 5); - AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - AddWaitStep("wait for tooltip to hide", 3); - - AddStep($"click null user {5}. {nameof(ClickableAvatar)}", () => - { - var targets = this.ChildrenOfType().ToList(); - if (targets.Count < 5) - return; - - InputManager.MoveMouseTo(targets[4]); - }); - AddWaitStep("wait for tooltip to show", 5); - AddStep("Hover out", () => InputManager.MoveMouseTo(new Vector2(0))); - AddWaitStep("wait for tooltip to hide", 3); + AddStep("hover avatar without user panel", () => InputManager.MoveMouseTo(this.ChildrenOfType().ElementAt(0))); + AddUntilStep("wait for tooltip to show", () => this.ChildrenOfType().FirstOrDefault()?.State.Value == Visibility.Visible); + AddStep("hover out", () => InputManager.MoveMouseTo(new Vector2(0))); + AddUntilStep("wait for tooltip to hide", () => this.ChildrenOfType().FirstOrDefault()?.State.Value == Visibility.Hidden); } private Drawable generateUser(string username, int id, CountryCode countryCode, string cover, bool showPanel, string? color = null) From aa9deecafe7ad9150d82bfa7015d7e21cf3888b5 Mon Sep 17 00:00:00 2001 From: Joshua Hegedus Date: Fri, 10 Nov 2023 11:37:23 +0100 Subject: [PATCH 18/20] added missing comment, fixed incorrect visibility --- osu.Game/Users/Drawables/ClickableAvatar.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index ef451df95d..1f1960714f 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -33,7 +33,7 @@ namespace osu.Game.Users.Drawables /// A clickable avatar for the specified user, with UI sounds included. /// /// The user. A null value will get a placeholder avatar. - /// + /// If set to true, the will be shown for the tooltip public ClickableAvatar(APIUser? user = null, bool showCardOnHover = false) { if (user?.Id != APIUser.SYSTEM_USER_ID) @@ -72,7 +72,11 @@ namespace osu.Game.Users.Drawables } protected override void PopIn() => this.FadeIn(150, Easing.OutQuint); - protected override void PopOut() => this.Delay(150).FadeOut(500, Easing.OutQuint); + protected override void PopOut() + { + this.Delay(150).FadeOut(500, Easing.OutQuint); + Clear(); + } public void Move(Vector2 pos) => Position = pos; From deef8998f73850d0e40247fa5854f042967e4687 Mon Sep 17 00:00:00 2001 From: Joshua Hegedus Date: Fri, 10 Nov 2023 11:45:31 +0100 Subject: [PATCH 19/20] reverted the change --- osu.Game/Users/Drawables/ClickableAvatar.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 1f1960714f..26622a1f30 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -72,11 +72,7 @@ namespace osu.Game.Users.Drawables } protected override void PopIn() => this.FadeIn(150, Easing.OutQuint); - protected override void PopOut() - { - this.Delay(150).FadeOut(500, Easing.OutQuint); - Clear(); - } + protected override void PopOut() => this.Delay(150).FadeOut(500, Easing.OutQuint); public void Move(Vector2 pos) => Position = pos; From 7b987266d50db8b3c5668a27625f7635a6eeefbc Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 14 Nov 2023 16:15:22 -0800 Subject: [PATCH 20/20] Change behavior of some clickable avatars in line with web --- osu.Game/Overlays/BeatmapSet/AuthorInfo.cs | 2 +- osu.Game/Overlays/Comments/CommentsContainer.cs | 2 +- osu.Game/Overlays/Comments/DrawableComment.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index 1d01495188..99ad5a5c7d 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -55,7 +55,7 @@ namespace osu.Game.Overlays.BeatmapSet AutoSizeAxes = Axes.Both, CornerRadius = 4, Masking = true, - Child = avatar = new UpdateableAvatar(showGuestOnNull: false) + Child = avatar = new UpdateableAvatar(showUserPanelOnHover: true, showGuestOnNull: false) { Size = new Vector2(height), }, diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index af5f4dd280..b4e9a80ff1 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -102,7 +102,7 @@ namespace osu.Game.Overlays.Comments Padding = new MarginPadding { Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING, Vertical = 20 }, Children = new Drawable[] { - avatar = new UpdateableAvatar(api.LocalUser.Value) + avatar = new UpdateableAvatar(api.LocalUser.Value, isInteractive: false) { Size = new Vector2(50), CornerExponent = 2, diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index ba1c7ca8b2..ceae17aa5d 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -144,7 +144,7 @@ namespace osu.Game.Overlays.Comments Size = new Vector2(avatar_size), Children = new Drawable[] { - new UpdateableAvatar(Comment.User) + new UpdateableAvatar(Comment.User, showUserPanelOnHover: true) { Size = new Vector2(avatar_size), Masking = true,