1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-14 23:33:23 +08:00

Merge pull request #22005 from bdach/user-profile/decouple-from-api-user

Decouple user profile overlay from `APIUser` model
This commit is contained in:
Dean Herbert 2023-01-11 16:27:00 +09:00 committed by GitHub
commit 5a5ea2c54a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 149 additions and 152 deletions

View File

@ -9,6 +9,7 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.Profile;
using osu.Game.Overlays.Profile.Sections;
namespace osu.Game.Tests.Visual.Online
@ -37,8 +38,8 @@ namespace osu.Game.Tests.Visual.Online
Child = section = new HistoricalSection(),
});
AddStep("Show peppy", () => section.User.Value = new APIUser { Id = 2 });
AddStep("Show WubWoofWolf", () => section.User.Value = new APIUser { Id = 39828 });
AddStep("Show peppy", () => section.User.Value = new UserProfileData(new APIUser { Id = 2 }));
AddStep("Show WubWoofWolf", () => section.User.Value = new UserProfileData(new APIUser { Id = 39828 }));
}
}
}

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Game.Overlays.Profile.Sections.Historical;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
@ -14,6 +12,7 @@ using System.Linq;
using osu.Framework.Testing;
using osu.Framework.Graphics.Shapes;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays.Profile;
namespace osu.Game.Tests.Visual.Online
{
@ -22,7 +21,7 @@ namespace osu.Game.Tests.Visual.Online
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Red);
private readonly Bindable<APIUser> user = new Bindable<APIUser>();
private readonly Bindable<UserProfileData?> user = new Bindable<UserProfileData?>();
private readonly PlayHistorySubsection section;
public TestScenePlayHistorySubsection()
@ -45,49 +44,49 @@ namespace osu.Game.Tests.Visual.Online
[Test]
public void TestNullValues()
{
AddStep("Load user", () => user.Value = user_with_null_values);
AddStep("Load user", () => user.Value = new UserProfileData(user_with_null_values));
AddAssert("Section is hidden", () => section.Alpha == 0);
}
[Test]
public void TestEmptyValues()
{
AddStep("Load user", () => user.Value = user_with_empty_values);
AddStep("Load user", () => user.Value = new UserProfileData(user_with_empty_values));
AddAssert("Section is hidden", () => section.Alpha == 0);
}
[Test]
public void TestOneValue()
{
AddStep("Load user", () => user.Value = user_with_one_value);
AddStep("Load user", () => user.Value = new UserProfileData(user_with_one_value));
AddAssert("Section is hidden", () => section.Alpha == 0);
}
[Test]
public void TestTwoValues()
{
AddStep("Load user", () => user.Value = user_with_two_values);
AddStep("Load user", () => user.Value = new UserProfileData(user_with_two_values));
AddAssert("Section is visible", () => section.Alpha == 1);
}
[Test]
public void TestConstantValues()
{
AddStep("Load user", () => user.Value = user_with_constant_values);
AddStep("Load user", () => user.Value = new UserProfileData(user_with_constant_values));
AddAssert("Section is visible", () => section.Alpha == 1);
}
[Test]
public void TestConstantZeroValues()
{
AddStep("Load user", () => user.Value = user_with_zero_values);
AddStep("Load user", () => user.Value = new UserProfileData(user_with_zero_values));
AddAssert("Section is visible", () => section.Alpha == 1);
}
[Test]
public void TestFilledValues()
{
AddStep("Load user", () => user.Value = user_with_filled_values);
AddStep("Load user", () => user.Value = new UserProfileData(user_with_filled_values));
AddAssert("Section is visible", () => section.Alpha == 1);
AddAssert("Array length is the same", () => user_with_filled_values.MonthlyPlayCounts.Length == getChartValuesLength());
}
@ -95,7 +94,7 @@ namespace osu.Game.Tests.Visual.Online
[Test]
public void TestMissingValues()
{
AddStep("Load user", () => user.Value = user_with_missing_values);
AddStep("Load user", () => user.Value = new UserProfileData(user_with_missing_values));
AddAssert("Section is visible", () => section.Alpha == 1);
AddAssert("Array length is 7", () => getChartValuesLength() == 7);
}

View File

@ -29,33 +29,33 @@ namespace osu.Game.Tests.Visual.Online
[Test]
public void TestBasic()
{
AddStep("Show example user", () => header.User.Value = TestSceneUserProfileOverlay.TEST_USER);
AddStep("Show example user", () => header.User.Value = new UserProfileData(TestSceneUserProfileOverlay.TEST_USER));
}
[Test]
public void TestOnlineState()
{
AddStep("Show online user", () => header.User.Value = new APIUser
AddStep("Show online user", () => header.User.Value = new UserProfileData(new APIUser
{
Id = 1001,
Username = "IAmOnline",
LastVisit = DateTimeOffset.Now,
IsOnline = true,
});
}));
AddStep("Show offline user", () => header.User.Value = new APIUser
AddStep("Show offline user", () => header.User.Value = new UserProfileData(new APIUser
{
Id = 1002,
Username = "IAmOffline",
LastVisit = DateTimeOffset.Now.AddDays(-10),
IsOnline = false,
});
}));
}
[Test]
public void TestRankedState()
{
AddStep("Show ranked user", () => header.User.Value = new APIUser
AddStep("Show ranked user", () => header.User.Value = new UserProfileData(new APIUser
{
Id = 2001,
Username = "RankedUser",
@ -70,9 +70,9 @@ namespace osu.Game.Tests.Visual.Online
Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray()
},
}
});
}));
AddStep("Show unranked user", () => header.User.Value = new APIUser
AddStep("Show unranked user", () => header.User.Value = new UserProfileData(new APIUser
{
Id = 2002,
Username = "UnrankedUser",
@ -86,7 +86,7 @@ namespace osu.Game.Tests.Visual.Online
Data = Enumerable.Range(2345, 85).ToArray()
},
}
});
}));
}
}
}

View File

@ -4,9 +4,12 @@
using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.Profile;
using osu.Game.Users;
namespace osu.Game.Tests.Visual.Online
@ -14,9 +17,41 @@ namespace osu.Game.Tests.Visual.Online
[TestFixture]
public partial class TestSceneUserProfileOverlay : OsuTestScene
{
protected override bool UseOnlineAPI => true;
private DummyAPIAccess dummyAPI => (DummyAPIAccess)API;
private readonly TestUserProfileOverlay profile;
private UserProfileOverlay profile = null!;
[SetUpSteps]
public void SetUp()
{
AddStep("create profile overlay", () => Child = profile = new UserProfileOverlay());
}
[Test]
public void TestBlank()
{
AddStep("show overlay", () => profile.Show());
}
[Test]
public void TestActualUser()
{
AddStep("set up request handling", () =>
{
dummyAPI.HandleRequest = req =>
{
if (req is GetUserRequest getUserRequest)
{
getUserRequest.TriggerSuccess(TEST_USER);
return true;
}
return false;
};
});
AddStep("show user", () => profile.ShowUser(new APIUser { Id = 1 }));
AddToggleStep("toggle visibility", visible => profile.State.Value = visible ? Visibility.Visible : Visibility.Hidden);
}
public static readonly APIUser TEST_USER = new APIUser
{
@ -64,60 +99,5 @@ namespace osu.Game.Tests.Visual.Online
Colour = "ff0000",
Achievements = Array.Empty<APIUserAchievement>(),
};
public TestSceneUserProfileOverlay()
{
Add(profile = new TestUserProfileOverlay());
}
protected override void LoadComplete()
{
base.LoadComplete();
AddStep("Show offline dummy", () => profile.ShowUser(TEST_USER));
AddStep("Show null dummy", () => profile.ShowUser(new APIUser
{
Username = @"Null",
Id = 1,
}));
AddStep("Show ppy", () => profile.ShowUser(new APIUser
{
Username = @"peppy",
Id = 2,
IsSupporter = true,
CountryCode = CountryCode.AU,
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg"
}));
AddStep("Show flyte", () => profile.ShowUser(new APIUser
{
Username = @"flyte",
Id = 3103765,
CountryCode = CountryCode.JP,
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"
}));
AddStep("Show bancho", () => profile.ShowUser(new APIUser
{
Username = @"BanchoBot",
Id = 3,
IsBot = true,
CountryCode = CountryCode.SH,
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c4.jpg"
}));
AddStep("Show ppy from username", () => profile.ShowUser(new APIUser { Username = @"peppy" }));
AddStep("Show flyte from username", () => profile.ShowUser(new APIUser { Username = @"flyte" }));
AddStep("Hide", profile.Hide);
AddStep("Show without reload", profile.Show);
}
private partial class TestUserProfileOverlay : UserProfileOverlay
{
public new ProfileHeader Header => base.Header;
}
}
}

View File

@ -10,6 +10,7 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.Profile;
using osu.Game.Overlays.Profile.Sections;
namespace osu.Game.Tests.Visual.Online
@ -44,7 +45,7 @@ namespace osu.Game.Tests.Visual.Online
}
});
AddStep("Show cookiezi", () => ranks.User.Value = new APIUser { Id = 124493 });
AddStep("Show cookiezi", () => ranks.User.Value = new UserProfileData(new APIUser { Id = 124493 }));
}
}
}

View File

@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Profile.Header
{
public partial class BottomHeaderContainer : CompositeDrawable
{
public readonly Bindable<APIUser?> User = new Bindable<APIUser?>();
public readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
private LinkFlowContainer topLinkContainer = null!;
private LinkFlowContainer bottomLinkContainer = null!;
@ -73,7 +73,7 @@ namespace osu.Game.Overlays.Profile.Header
}
};
User.BindValueChanged(user => updateDisplay(user.NewValue));
User.BindValueChanged(user => updateDisplay(user.NewValue?.User));
}
private void updateDisplay(APIUser? user)

View File

@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Profile.Header
public partial class CentreHeaderContainer : CompositeDrawable
{
public readonly BindableBool DetailsVisible = new BindableBool(true);
public readonly Bindable<APIUser?> User = new Bindable<APIUser?>();
public readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
private OverlinedInfoContainer hiddenDetailGlobal = null!;
private OverlinedInfoContainer hiddenDetailCountry = null!;
@ -141,7 +141,7 @@ namespace osu.Game.Overlays.Profile.Header
expandedDetailContainer.FadeTo(visible.NewValue ? 1 : 0, 200, Easing.OutQuint);
});
User.BindValueChanged(user => updateDisplay(user.NewValue));
User.BindValueChanged(user => updateDisplay(user.NewValue?.User));
}
private void updateDisplay(APIUser? user)

View File

@ -5,14 +5,13 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.Profile.Header.Components
{
public partial class FollowersButton : ProfileHeaderStatisticsButton
{
public readonly Bindable<APIUser?> User = new Bindable<APIUser?>();
public readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
public override LocalisableString TooltipText => FriendsStrings.ButtonsDisabled;
@ -22,7 +21,7 @@ namespace osu.Game.Overlays.Profile.Header.Components
private void load()
{
// todo: when friending/unfriending is implemented, the APIAccess.Friends list should be updated accordingly.
User.BindValueChanged(user => SetValue(user.NewValue?.FollowerCount ?? 0), true);
User.BindValueChanged(user => SetValue(user.NewValue?.User.FollowerCount ?? 0), true);
}
}
}

View File

@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Profile.Header.Components
{
public partial class LevelBadge : CompositeDrawable, IHasTooltip
{
public readonly Bindable<APIUser?> User = new Bindable<APIUser?>();
public readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
public LocalisableString TooltipText { get; private set; }
@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Profile.Header.Components
}
};
User.BindValueChanged(user => updateLevel(user.NewValue));
User.BindValueChanged(user => updateLevel(user.NewValue?.User));
}
private void updateLevel(APIUser? user)

View File

@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Profile.Header.Components
{
public partial class LevelProgressBar : CompositeDrawable, IHasTooltip
{
public readonly Bindable<APIUser?> User = new Bindable<APIUser?>();
public readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
public LocalisableString TooltipText { get; }
@ -56,7 +56,7 @@ namespace osu.Game.Overlays.Profile.Header.Components
}
};
User.BindValueChanged(user => updateProgress(user.NewValue));
User.BindValueChanged(user => updateProgress(user.NewValue?.User));
}
private void updateProgress(APIUser? user)

View File

@ -5,14 +5,13 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.Profile.Header.Components
{
public partial class MappingSubscribersButton : ProfileHeaderStatisticsButton
{
public readonly Bindable<APIUser?> User = new Bindable<APIUser?>();
public readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
public override LocalisableString TooltipText => FollowsStrings.MappingFollowers;
@ -21,7 +20,7 @@ namespace osu.Game.Overlays.Profile.Header.Components
[BackgroundDependencyLoader]
private void load()
{
User.BindValueChanged(user => SetValue(user.NewValue?.MappingFollowerCount ?? 0), true);
User.BindValueChanged(user => SetValue(user.NewValue?.User.MappingFollowerCount ?? 0), true);
}
}
}

View File

@ -7,7 +7,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Chat;
using osu.Game.Resources.Localisation.Web;
using osuTK;
@ -16,7 +15,7 @@ namespace osu.Game.Overlays.Profile.Header.Components
{
public partial class MessageUserButton : ProfileHeaderButton
{
public readonly Bindable<APIUser?> User = new Bindable<APIUser?>();
public readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
public override LocalisableString TooltipText => UsersStrings.CardSendMessage;
@ -49,12 +48,16 @@ namespace osu.Game.Overlays.Profile.Header.Components
{
if (!Content.IsPresent) return;
channelManager?.OpenPrivateChannel(User.Value);
channelManager?.OpenPrivateChannel(User.Value?.User);
userOverlay?.Hide();
chatOverlay?.Show();
};
User.ValueChanged += e => Content.Alpha = e.NewValue != null && !e.NewValue.PMFriendsOnly && apiProvider.LocalUser.Value.Id != e.NewValue.Id ? 1 : 0;
User.ValueChanged += e =>
{
var user = e.NewValue?.User;
Content.Alpha = user != null && !user.PMFriendsOnly && apiProvider.LocalUser.Value.Id != user.Id ? 1 : 0;
};
}
}
}

View File

@ -7,14 +7,13 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Localisation;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.Profile.Header.Components
{
public partial class OverlinedTotalPlayTime : CompositeDrawable, IHasTooltip
{
public readonly Bindable<APIUser?> User = new Bindable<APIUser?>();
public readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
public LocalisableString TooltipText { get; set; }
@ -39,10 +38,11 @@ namespace osu.Game.Overlays.Profile.Header.Components
User.BindValueChanged(updateTime, true);
}
private void updateTime(ValueChangedEvent<APIUser?> user)
private void updateTime(ValueChangedEvent<UserProfileData?> user)
{
TooltipText = (user.NewValue?.Statistics?.PlayTime ?? 0) / 3600 + " hours";
info.Content = formatTime(user.NewValue?.Statistics?.PlayTime);
int? playTime = user.NewValue?.User.Statistics?.PlayTime;
TooltipText = (playTime ?? 0) / 3600 + " hours";
info.Content = formatTime(playTime);
}
private string formatTime(int? secondsNull)

View File

@ -11,7 +11,6 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Localisation;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Leaderboards;
using osu.Game.Overlays.Profile.Header.Components;
using osu.Game.Resources.Localisation.Web;
@ -30,7 +29,7 @@ namespace osu.Game.Overlays.Profile.Header
private FillFlowContainer? fillFlow;
private RankGraph rankGraph = null!;
public readonly Bindable<APIUser?> User = new Bindable<APIUser?>();
public readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
private bool expanded = true;
@ -171,8 +170,10 @@ namespace osu.Game.Overlays.Profile.Header
};
}
private void updateDisplay(APIUser? user)
private void updateDisplay(UserProfileData? data)
{
var user = data?.User;
medalInfo.Content = user?.Achievements?.Length.ToString() ?? "0";
ppInfo.Content = user?.Statistics?.PP?.ToLocalisableString("#,##0") ?? (LocalisableString)"0";

View File

@ -20,14 +20,14 @@ namespace osu.Game.Overlays.Profile.Header
{
private FillFlowContainer badgeFlowContainer = null!;
public readonly Bindable<APIUser?> User = new Bindable<APIUser?>();
public readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider)
{
Alpha = 0;
AutoSizeAxes = Axes.Y;
User.ValueChanged += e => updateDisplay(e.NewValue);
User.ValueChanged += e => updateDisplay(e.NewValue?.User);
InternalChildren = new Drawable[]
{

View File

@ -15,7 +15,6 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.Cursor;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays.Profile.Header.Components;
using osu.Game.Resources.Localisation.Web;
using osu.Game.Users.Drawables;
@ -27,7 +26,7 @@ namespace osu.Game.Overlays.Profile.Header
{
private const float avatar_size = 110;
public readonly Bindable<APIUser?> User = new Bindable<APIUser?>();
public readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
[Resolved]
private IAPIProvider api { get; set; } = null!;
@ -174,8 +173,10 @@ namespace osu.Game.Overlays.Profile.Header
User.BindValueChanged(user => updateUser(user.NewValue));
}
private void updateUser(APIUser? user)
private void updateUser(UserProfileData? data)
{
var user = data?.User;
avatar.User = user;
usernameText.Text = user?.Username ?? string.Empty;
openUserExternally.Link = $@"{api.WebsiteRootUrl}/users/{user?.Id ?? 0}";

View File

@ -9,7 +9,6 @@ using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Localisation;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays.Profile.Header;
using osu.Game.Resources.Localisation.Web;
using osu.Game.Users;
@ -20,7 +19,7 @@ namespace osu.Game.Overlays.Profile
{
private UserCoverBackground coverContainer = null!;
public Bindable<APIUser?> User = new Bindable<APIUser?>();
public Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
private CentreHeaderContainer centreHeaderContainer;
private DetailHeaderContainer detailHeaderContainer;
@ -100,7 +99,7 @@ namespace osu.Game.Overlays.Profile
protected override OverlayTitle CreateTitle() => new ProfileHeaderTitle();
private void updateDisplay(APIUser? user) => coverContainer.User = user;
private void updateDisplay(UserProfileData? user) => coverContainer.User = user?.User;
private partial class ProfileHeaderTitle : OverlayTitle
{

View File

@ -13,7 +13,6 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.Profile
{
@ -29,7 +28,7 @@ namespace osu.Game.Overlays.Profile
protected override Container<Drawable> Content => content;
public readonly Bindable<APIUser?> User = new Bindable<APIUser?>();
public readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
protected ProfileSection()
{

View File

@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
protected override int InitialItemsCount => type == BeatmapSetType.Graveyard ? 2 : 6;
public PaginatedBeatmapContainer(BeatmapSetType type, Bindable<APIUser?> user, LocalisableString headerText)
public PaginatedBeatmapContainer(BeatmapSetType type, Bindable<UserProfileData?> user, LocalisableString headerText)
: base(user, headerText)
{
this.type = type;

View File

@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
/// </summary>
protected abstract LocalisableString GraphCounterName { get; }
protected ChartProfileSubsection(Bindable<APIUser?> user, LocalisableString headerText)
protected ChartProfileSubsection(Bindable<UserProfileData?> user, LocalisableString headerText)
: base(user, headerText)
{
}
@ -44,9 +44,9 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
User.BindValueChanged(onUserChanged, true);
}
private void onUserChanged(ValueChangedEvent<APIUser?> e)
private void onUserChanged(ValueChangedEvent<UserProfileData?> e)
{
var values = GetValues(e.NewValue);
var values = GetValues(e.NewValue?.User);
if (values == null || values.Length <= 1)
{

View File

@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
{
public partial class PaginatedMostPlayedBeatmapContainer : PaginatedProfileSubsection<APIUserMostPlayedBeatmap>
{
public PaginatedMostPlayedBeatmapContainer(Bindable<APIUser?> user)
public PaginatedMostPlayedBeatmapContainer(Bindable<UserProfileData?> user)
: base(user, UsersStrings.ShowExtraHistoricalMostPlayedTitle)
{
}

View File

@ -12,7 +12,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
{
protected override LocalisableString GraphCounterName => UsersStrings.ShowExtraHistoricalMonthlyPlaycountsCountLabel;
public PlayHistorySubsection(Bindable<APIUser?> user)
public PlayHistorySubsection(Bindable<UserProfileData?> user)
: base(user, UsersStrings.ShowExtraHistoricalMonthlyPlaycountsTitle)
{
}

View File

@ -12,7 +12,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
{
protected override LocalisableString GraphCounterName => UsersStrings.ShowExtraHistoricalReplaysWatchedCountsCountLabel;
public ReplaysSubsection(Bindable<APIUser?> user)
public ReplaysSubsection(Bindable<UserProfileData?> user)
: base(user, UsersStrings.ShowExtraHistoricalReplaysWatchedCountsTitle)
{
}

View File

@ -14,15 +14,14 @@ using osu.Framework.Allocation;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Game.Resources.Localisation.Web;
using osu.Framework.Localisation;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.Profile.Sections.Kudosu
{
public partial class KudosuInfo : Container
{
private readonly Bindable<APIUser?> user = new Bindable<APIUser?>();
private readonly Bindable<UserProfileData?> user = new Bindable<UserProfileData?>();
public KudosuInfo(Bindable<APIUser?> user)
public KudosuInfo(Bindable<UserProfileData?> user)
{
this.user.BindTo(user);
CountSection total;
@ -32,7 +31,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu
CornerRadius = 3;
Child = total = new CountTotal();
this.user.ValueChanged += u => total.Count = u.NewValue?.Kudosu.Total ?? 0;
this.user.ValueChanged += u => total.Count = u.NewValue?.User.Kudosu.Total ?? 0;
}
protected override bool OnClick(ClickEvent e) => true;

View File

@ -14,7 +14,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu
{
public partial class PaginatedKudosuHistoryContainer : PaginatedProfileSubsection<APIKudosuHistory>
{
public PaginatedKudosuHistoryContainer(Bindable<APIUser?> user)
public PaginatedKudosuHistoryContainer(Bindable<UserProfileData?> user)
: base(user, missingText: UsersStrings.ShowExtraKudosuEntryEmpty)
{
}

View File

@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Profile.Sections
private OsuSpriteText missing = null!;
private readonly LocalisableString? missingText;
protected PaginatedProfileSubsection(Bindable<APIUser?> user, LocalisableString? headerText = null, LocalisableString? missingText = null)
protected PaginatedProfileSubsection(Bindable<UserProfileData?> user, LocalisableString? headerText = null, LocalisableString? missingText = null)
: base(user, headerText, CounterVisibilityState.AlwaysVisible)
{
this.missingText = missingText;
@ -92,7 +92,7 @@ namespace osu.Game.Overlays.Profile.Sections
User.BindValueChanged(onUserChanged, true);
}
private void onUserChanged(ValueChangedEvent<APIUser?> e)
private void onUserChanged(ValueChangedEvent<UserProfileData?> e)
{
loadCancellation?.Cancel();
retrievalRequest?.Cancel();
@ -100,23 +100,23 @@ namespace osu.Game.Overlays.Profile.Sections
CurrentPage = null;
ItemsContainer.Clear();
if (e.NewValue != null)
if (e.NewValue?.User != null)
{
showMore();
SetCount(GetCount(e.NewValue));
SetCount(GetCount(e.NewValue.User));
}
}
private void showMore()
{
if (User.Value == null)
if (User.Value?.User == null)
return;
loadCancellation = new CancellationTokenSource();
CurrentPage = CurrentPage?.TakeNext(ItemsPerPage) ?? new PaginationParameters(InitialItemsCount);
retrievalRequest = CreateRequest(User.Value, CurrentPage.Value);
retrievalRequest = CreateRequest(User.Value.User, CurrentPage.Value);
retrievalRequest.Success += items => UpdateItems(items, loadCancellation);
api.Queue(retrievalRequest);

View File

@ -6,20 +6,19 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Localisation;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.Profile.Sections
{
public abstract partial class ProfileSubsection : FillFlowContainer
{
protected readonly Bindable<APIUser?> User = new Bindable<APIUser?>();
protected readonly Bindable<UserProfileData?> User = new Bindable<UserProfileData?>();
private readonly LocalisableString headerText;
private readonly CounterVisibilityState counterVisibilityState;
private ProfileSubsectionHeader header = null!;
protected ProfileSubsection(Bindable<APIUser?> user, LocalisableString? headerText = null, CounterVisibilityState counterVisibilityState = CounterVisibilityState.AlwaysHidden)
protected ProfileSubsection(Bindable<UserProfileData?> user, LocalisableString? headerText = null, CounterVisibilityState counterVisibilityState = CounterVisibilityState.AlwaysHidden)
{
this.headerText = headerText ?? string.Empty;
this.counterVisibilityState = counterVisibilityState;

View File

@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
{
private readonly ScoreType type;
public PaginatedScoreContainer(ScoreType type, Bindable<APIUser?> user, LocalisableString headerText)
public PaginatedScoreContainer(ScoreType type, Bindable<UserProfileData?> user, LocalisableString headerText)
: base(user, headerText)
{
this.type = type;

View File

@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
{
public partial class PaginatedRecentActivityContainer : PaginatedProfileSubsection<APIRecentActivity>
{
public PaginatedRecentActivityContainer(Bindable<APIUser?> user)
public PaginatedRecentActivityContainer(Bindable<UserProfileData?> user)
: base(user, missingText: EventsStrings.Empty)
{
}

View File

@ -0,0 +1,25 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.Profile
{
/// <summary>
/// Contains data about a profile presented on the <see cref="UserProfileOverlay"/>.
/// </summary>
public class UserProfileData
{
/// <summary>
/// The user whose profile is being presented.
/// </summary>
public APIUser User { get; }
// TODO: add ruleset
public UserProfileData(APIUser user)
{
User = user;
}
}
}

View File

@ -47,7 +47,7 @@ namespace osu.Game.Overlays
Show();
if (user.OnlineID == Header?.User.Value?.Id)
if (user.OnlineID == Header?.User.Value?.User.Id)
return;
if (sectionsContainer != null)
@ -116,15 +116,6 @@ namespace osu.Game.Overlays
sectionsContainer.ScrollToTop();
// Check arbitrarily whether this user has already been populated.
// This is only generally used by tests, but should be quite safe unless we want to force a refresh on loading a previous user in the future.
if (user is APIUser apiUser && apiUser.JoinDate != default)
{
userReq = null;
userLoadComplete(apiUser);
return;
}
userReq = user.OnlineID > 1 ? new GetUserRequest(user.OnlineID) : new GetUserRequest(user.Username);
userReq.Success += userLoadComplete;
API.Queue(userReq);
@ -134,7 +125,8 @@ namespace osu.Game.Overlays
{
Debug.Assert(sections != null && sectionsContainer != null && tabs != null);
Header.User.Value = user;
var userProfile = new UserProfileData(user);
Header.User.Value = userProfile;
if (user.ProfileOrder != null)
{
@ -144,7 +136,7 @@ namespace osu.Game.Overlays
if (sec != null)
{
sec.User.Value = user;
sec.User.Value = userProfile;
sectionsContainer.Add(sec);
tabs.AddItem(sec);