Update favourite statistic value on favourite button clicks

This commit is contained in:
Bartłomiej Dach 2021-11-07 17:42:32 +01:00
parent b5cbdcf981
commit f4b8dee2d0
No known key found for this signature in database
GPG Key ID: BCECCD4FA41F6497
5 changed files with 106 additions and 16 deletions

View File

@ -9,8 +9,11 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables.Cards;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osuTK;
@ -20,6 +23,8 @@ namespace osu.Game.Tests.Visual.Beatmaps
{
public class TestSceneBeatmapCard : OsuTestScene
{
private DummyAPIAccess dummyAPI => (DummyAPIAccess)API;
private APIBeatmapSet[] testCases;
#region Test case generation
@ -164,6 +169,19 @@ namespace osu.Game.Tests.Visual.Beatmaps
#endregion
[SetUpSteps]
public void SetUpSteps()
{
AddStep("register request handling", () => dummyAPI.HandleRequest = request =>
{
if (!(request is PostBeatmapFavouriteRequest))
return false;
request.TriggerSuccess();
return true;
});
}
private Drawable createContent(OverlayColourScheme colourScheme, Func<APIBeatmapSet, Drawable> creationFunc)
{
var colourProvider = new OverlayColourProvider(colourScheme);

View File

@ -3,6 +3,7 @@
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
@ -35,6 +36,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
private const float corner_radius = 10;
private readonly APIBeatmapSet beatmapSet;
private readonly Bindable<BeatmapSetFavouriteState> favouriteState;
private UpdateableOnlineBeatmapSetCover leftCover;
private FillFlowContainer leftIconArea;
@ -55,6 +57,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
: base(HoverSampleSet.Submit)
{
this.beatmapSet = beatmapSet;
favouriteState = new Bindable<BeatmapSetFavouriteState>(new BeatmapSetFavouriteState(beatmapSet.HasFavourited, beatmapSet.FavouriteCount));
}
[BackgroundDependencyLoader]
@ -108,7 +111,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
Spacing = new Vector2(0, 14),
Children = new BeatmapCardIconButton[]
{
new FavouriteButton(beatmapSet),
new FavouriteButton(beatmapSet) { Current = favouriteState },
new DownloadButton(beatmapSet)
}
}
@ -312,7 +315,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
if (beatmapSet.HypeStatus != null && beatmapSet.NominationStatus != null)
yield return new NominationsStatistic(beatmapSet.NominationStatus);
yield return new FavouritesStatistic(beatmapSet);
yield return new FavouritesStatistic(beatmapSet) { Current = favouriteState };
yield return new PlayCountStatistic(beatmapSet);
var dateStatistic = BeatmapCardDateStatistic.CreateFor(beatmapSet);

View File

@ -0,0 +1,31 @@
// 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.Beatmaps.Drawables.Cards.Buttons;
using osu.Game.Beatmaps.Drawables.Cards.Statistics;
namespace osu.Game.Beatmaps.Drawables.Cards
{
/// <summary>
/// Stores the current favourite state of a beatmap set.
/// Used to coordinate between <see cref="FavouriteButton"/> and <see cref="FavouritesStatistic"/>.
/// </summary>
public readonly struct BeatmapSetFavouriteState
{
/// <summary>
/// Whether the currently logged-in user has favourited this beatmap.
/// </summary>
public bool Favourited { get; }
/// <summary>
/// The number of favourites that the beatmap set has received, including the currently logged-in user.
/// </summary>
public int FavouriteCount { get; }
public BeatmapSetFavouriteState(bool favourited, int favouriteCount)
{
Favourited = favourited;
FavouriteCount = favouriteCount;
}
}
}

View File

@ -2,7 +2,9 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Online.API.Requests.Responses;
using osu.Framework.Logging;
using osu.Game.Online.API;
@ -11,17 +13,24 @@ using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
{
public class FavouriteButton : BeatmapCardIconButton
public class FavouriteButton : BeatmapCardIconButton, IHasCurrentValue<BeatmapSetFavouriteState>
{
private readonly APIBeatmapSet beatmapSet;
private readonly BindableWithCurrent<BeatmapSetFavouriteState> current;
public Bindable<BeatmapSetFavouriteState> Current
{
get => current.Current;
set => current.Current = value;
}
private readonly int onlineBeatmapID;
private PostBeatmapFavouriteRequest favouriteRequest;
public FavouriteButton(APIBeatmapSet beatmapSet)
{
this.beatmapSet = beatmapSet;
updateState();
current = new BindableWithCurrent<BeatmapSetFavouriteState>(new BeatmapSetFavouriteState(beatmapSet.HasFavourited, beatmapSet.FavouriteCount));
onlineBeatmapID = beatmapSet.OnlineID;
}
[BackgroundDependencyLoader]
@ -29,17 +38,19 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
{
Action = () =>
{
var actionType = beatmapSet.HasFavourited ? BeatmapFavouriteAction.UnFavourite : BeatmapFavouriteAction.Favourite;
var actionType = current.Value.Favourited ? BeatmapFavouriteAction.UnFavourite : BeatmapFavouriteAction.Favourite;
favouriteRequest?.Cancel();
favouriteRequest = new PostBeatmapFavouriteRequest(beatmapSet.OnlineID, actionType);
favouriteRequest = new PostBeatmapFavouriteRequest(onlineBeatmapID, actionType);
Enabled.Value = false;
favouriteRequest.Success += () =>
{
beatmapSet.HasFavourited = actionType == BeatmapFavouriteAction.Favourite;
bool favourited = actionType == BeatmapFavouriteAction.Favourite;
current.Value = new BeatmapSetFavouriteState(favourited, current.Value.FavouriteCount + (favourited ? 1 : -1));
Enabled.Value = true;
updateState();
};
favouriteRequest.Failure += e =>
{
@ -51,9 +62,15 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
};
}
protected override void LoadComplete()
{
base.LoadComplete();
current.BindValueChanged(_ => updateState(), true);
}
private void updateState()
{
if (beatmapSet.HasFavourited)
if (current.Value.Favourited)
{
Icon.Icon = FontAwesome.Solid.Heart;
TooltipText = BeatmapsetsStrings.ShowDetailsUnfavourite;

View File

@ -2,8 +2,10 @@
// See the LICENCE file in the repository root for full licence text.
using Humanizer;
using osu.Framework.Bindables;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Beatmaps.Drawables.Cards.Statistics
@ -11,13 +13,32 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Statistics
/// <summary>
/// Shows the number of favourites that a beatmap set has received.
/// </summary>
public class FavouritesStatistic : BeatmapCardStatistic
public class FavouritesStatistic : BeatmapCardStatistic, IHasCurrentValue<BeatmapSetFavouriteState>
{
private readonly BindableWithCurrent<BeatmapSetFavouriteState> current;
public Bindable<BeatmapSetFavouriteState> Current
{
get => current.Current;
set => current.Current = value;
}
public FavouritesStatistic(IBeatmapSetOnlineInfo onlineInfo)
{
Icon = onlineInfo.HasFavourited ? FontAwesome.Solid.Heart : FontAwesome.Regular.Heart;
Text = onlineInfo.FavouriteCount.ToMetric(decimals: 1);
TooltipText = BeatmapsStrings.PanelFavourites(onlineInfo.FavouriteCount.ToLocalisableString(@"N0"));
current = new BindableWithCurrent<BeatmapSetFavouriteState>(new BeatmapSetFavouriteState(onlineInfo.HasFavourited, onlineInfo.FavouriteCount));
}
protected override void LoadComplete()
{
base.LoadComplete();
current.BindValueChanged(_ => updateState(), true);
}
private void updateState()
{
Icon = current.Value.Favourited ? FontAwesome.Solid.Heart : FontAwesome.Regular.Heart;
Text = current.Value.FavouriteCount.ToMetric(decimals: 1);
TooltipText = BeatmapsStrings.PanelFavourites(current.Value.FavouriteCount.ToLocalisableString(@"N0"));
}
}
}