diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index 91928c1fd2..a97c8aff66 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -121,6 +121,12 @@ namespace osu.Game.Tests.Visual.Online Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray() }, }, + TournamentBanner = new TournamentBanner + { + Id = 13926, + TournamentId = 35, + ImageLowRes = "https://assets.ppy.sh/tournament-banners/official/owc2022/profile/winner_US.jpg", + }, Badges = new[] { new Badge diff --git a/osu.Game/Online/API/Requests/Responses/APIUser.cs b/osu.Game/Online/API/Requests/Responses/APIUser.cs index 0e62b03f1a..e63395fe26 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUser.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUser.cs @@ -234,6 +234,10 @@ namespace osu.Game.Online.API.Requests.Responses set => Statistics.RankHistory = value; } + [JsonProperty(@"active_tournament_banner")] + [CanBeNull] + public TournamentBanner TournamentBanner; + [JsonProperty("badges")] public Badge[] Badges; diff --git a/osu.Game/Overlays/Profile/Header/BannerHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BannerHeaderContainer.cs new file mode 100644 index 0000000000..8e6648dc4b --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/BannerHeaderContainer.cs @@ -0,0 +1,63 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Threading; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays.Profile.Header.Components; + +namespace osu.Game.Overlays.Profile.Header +{ + public partial class BannerHeaderContainer : CompositeDrawable + { + public readonly Bindable User = new Bindable(); + + [BackgroundDependencyLoader] + private void load() + { + Alpha = 0; + RelativeSizeAxes = Axes.Both; + FillMode = FillMode.Fit; + FillAspectRatio = 1000 / 60f; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + User.BindValueChanged(u => updateDisplay(u.NewValue?.User), true); + } + + private CancellationTokenSource? cancellationTokenSource; + + private void updateDisplay(APIUser? user) + { + cancellationTokenSource?.Cancel(); + cancellationTokenSource = new CancellationTokenSource(); + + ClearInternal(); + + var banner = user?.TournamentBanner; + + if (banner != null) + { + Show(); + + LoadComponentAsync(new DrawableTournamentBanner(banner), AddInternal, cancellationTokenSource.Token); + } + else + { + Hide(); + } + } + + protected override void Dispose(bool isDisposing) + { + cancellationTokenSource?.Cancel(); + base.Dispose(isDisposing); + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/Components/DrawableTournamentBanner.cs b/osu.Game/Overlays/Profile/Header/Components/DrawableTournamentBanner.cs new file mode 100644 index 0000000000..26d333ff95 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/Components/DrawableTournamentBanner.cs @@ -0,0 +1,46 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Localisation; +using osu.Game.Graphics.Containers; +using osu.Game.Online.API; +using osu.Game.Users; + +namespace osu.Game.Overlays.Profile.Header.Components +{ + [LongRunningLoad] + public partial class DrawableTournamentBanner : OsuClickableContainer + { + private readonly TournamentBanner banner; + + public DrawableTournamentBanner(TournamentBanner banner) + { + this.banner = banner; + RelativeSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load(LargeTextureStore textures, OsuGame? game, IAPIProvider api) + { + Child = new Sprite + { + RelativeSizeAxes = Axes.Both, + Texture = textures.Get(banner.Image), + }; + + Action = () => game?.OpenUrlExternally($@"{api.WebsiteRootUrl}/community/tournaments/{banner.TournamentId}"); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + this.FadeInFromZero(200); + } + + public override LocalisableString TooltipText => "view in browser"; + } +} diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 5d753dea7d..363eb5d58e 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -47,6 +47,10 @@ namespace osu.Game.Overlays.Profile RelativeSizeAxes = Axes.X, User = { BindTarget = User }, }, + new BannerHeaderContainer + { + User = { BindTarget = User }, + }, new BadgeHeaderContainer { RelativeSizeAxes = Axes.X, diff --git a/osu.Game/Users/TournamentBanner.cs b/osu.Game/Users/TournamentBanner.cs new file mode 100644 index 0000000000..62e1913412 --- /dev/null +++ b/osu.Game/Users/TournamentBanner.cs @@ -0,0 +1,23 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.IO; +using Newtonsoft.Json; + +namespace osu.Game.Users +{ + public class TournamentBanner + { + [JsonProperty("id")] + public int Id; + + [JsonProperty("tournament_id")] + public int TournamentId; + + [JsonProperty("image")] + public string ImageLowRes = null!; + + // TODO: remove when api returns @2x image link: https://github.com/ppy/osu-web/issues/9816 + public string Image => $@"{Path.ChangeExtension(ImageLowRes, null)}@2x{Path.GetExtension(ImageLowRes)}"; + } +}