Skip to content

Commit

Permalink
Update favourite statistic value on favourite button clicks
Browse files Browse the repository at this point in the history
  • Loading branch information
bdach committed Nov 8, 2021
1 parent b5cbdcf commit f4b8dee
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 16 deletions.
18 changes: 18 additions & 0 deletions osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
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;
Expand All @@ -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
Expand Down Expand Up @@ -164,6 +169,19 @@ private static APIBeatmapSet getManyDifficultiesBeatmapSet(int count)

#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);
Expand Down
7 changes: 5 additions & 2 deletions osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -35,6 +36,7 @@ public class BeatmapCard : OsuClickableContainer
private const float corner_radius = 10;

private readonly APIBeatmapSet beatmapSet;
private readonly Bindable<BeatmapSetFavouriteState> favouriteState;

private UpdateableOnlineBeatmapSetCover leftCover;
private FillFlowContainer leftIconArea;
Expand All @@ -55,6 +57,7 @@ public BeatmapCard(APIBeatmapSet beatmapSet)
: base(HoverSampleSet.Submit)
{
this.beatmapSet = beatmapSet;
favouriteState = new Bindable<BeatmapSetFavouriteState>(new BeatmapSetFavouriteState(beatmapSet.HasFavourited, beatmapSet.FavouriteCount));
}

[BackgroundDependencyLoader]
Expand Down Expand Up @@ -108,7 +111,7 @@ private void load()
Spacing = new Vector2(0, 14),
Children = new BeatmapCardIconButton[]
{
new FavouriteButton(beatmapSet),
new FavouriteButton(beatmapSet) { Current = favouriteState },
new DownloadButton(beatmapSet)
}
}
Expand Down Expand Up @@ -312,7 +315,7 @@ private IEnumerable<BeatmapCardStatistic> createStatistics()
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);
Expand Down
31 changes: 31 additions & 0 deletions osu.Game/Beatmaps/Drawables/Cards/BeatmapSetFavouriteState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. 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;
}
}
}
37 changes: 27 additions & 10 deletions osu.Game/Beatmaps/Drawables/Cards/Buttons/FavouriteButton.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -11,35 +13,44 @@

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]
private void load(IAPIProvider api)
{
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 =>
{
Expand All @@ -51,9 +62,15 @@ private void load(IAPIProvider api)
};
}

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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,43 @@
// 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
{
/// <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"));
}
}
}

0 comments on commit f4b8dee

Please sign in to comment.