mirror of
https://github.com/osukey/osukey.git
synced 2025-06-27 14:18:06 +09:00
Merge pull request #16012 from bdach/beatmap-card/extra
Implement "extra" beatmap card size
This commit is contained in:
commit
2707b2fbda
@ -96,6 +96,7 @@ namespace osu.Game.Tests.Visual.Beatmaps
|
|||||||
var longName = CreateAPIBeatmapSet(Ruleset.Value);
|
var longName = CreateAPIBeatmapSet(Ruleset.Value);
|
||||||
longName.Title = longName.TitleUnicode = "this track has an incredibly and implausibly long title";
|
longName.Title = longName.TitleUnicode = "this track has an incredibly and implausibly long title";
|
||||||
longName.Artist = longName.ArtistUnicode = "and this artist! who would have thunk it. it's really such a long name.";
|
longName.Artist = longName.ArtistUnicode = "and this artist! who would have thunk it. it's really such a long name.";
|
||||||
|
longName.Source = "wow. even the source field has an impossibly long string in it. this really takes the cake, doesn't it?";
|
||||||
longName.HasExplicitContent = true;
|
longName.HasExplicitContent = true;
|
||||||
longName.TrackId = 444;
|
longName.TrackId = 444;
|
||||||
|
|
||||||
@ -254,6 +255,12 @@ namespace osu.Game.Tests.Visual.Beatmaps
|
|||||||
createTestCase(beatmapSetInfo => new BeatmapCard(beatmapSetInfo));
|
createTestCase(beatmapSetInfo => new BeatmapCard(beatmapSetInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestExtra()
|
||||||
|
{
|
||||||
|
createTestCase(beatmapSetInfo => new BeatmapCardExtra(beatmapSetInfo));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestHoverState()
|
public void TestHoverState()
|
||||||
{
|
{
|
||||||
|
@ -5,109 +5,68 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Input.Events;
|
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Beatmaps.Drawables.Cards.Buttons;
|
|
||||||
using osu.Game.Beatmaps.Drawables.Cards.Statistics;
|
using osu.Game.Beatmaps.Drawables.Cards.Statistics;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osu.Game.Online;
|
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Overlays.BeatmapSet;
|
using osu.Game.Overlays.BeatmapSet;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osu.Game.Resources.Localisation.Web;
|
using osu.Game.Resources.Localisation.Web;
|
||||||
using DownloadButton = osu.Game.Beatmaps.Drawables.Cards.Buttons.DownloadButton;
|
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps.Drawables.Cards
|
namespace osu.Game.Beatmaps.Drawables.Cards
|
||||||
{
|
{
|
||||||
public class BeatmapCard : OsuClickableContainer
|
public class BeatmapCard : BeatmapCardBase
|
||||||
{
|
{
|
||||||
public const float TRANSITION_DURATION = 400;
|
protected override Drawable IdleContent => idleBottomContent;
|
||||||
public const float CORNER_RADIUS = 10;
|
protected override Drawable DownloadInProgressContent => downloadProgressBar;
|
||||||
|
|
||||||
public IBindable<bool> Expanded { get; }
|
|
||||||
|
|
||||||
private const float width = 408;
|
private const float width = 408;
|
||||||
private const float height = 100;
|
private const float height = 100;
|
||||||
private const float icon_area_width = 30;
|
|
||||||
|
|
||||||
private readonly APIBeatmapSet beatmapSet;
|
[Cached]
|
||||||
private readonly Bindable<BeatmapSetFavouriteState> favouriteState;
|
private readonly BeatmapCardContent content;
|
||||||
|
|
||||||
private readonly BeatmapDownloadTracker downloadTracker;
|
|
||||||
|
|
||||||
private BeatmapCardContent content = null!;
|
|
||||||
|
|
||||||
private BeatmapCardThumbnail thumbnail = null!;
|
private BeatmapCardThumbnail thumbnail = null!;
|
||||||
|
private CollapsibleButtonContainer buttonContainer = null!;
|
||||||
|
|
||||||
private Container rightAreaBackground = null!;
|
|
||||||
private Container<BeatmapCardIconButton> rightAreaButtons = null!;
|
|
||||||
|
|
||||||
private Container mainContent = null!;
|
|
||||||
private BeatmapCardContentBackground mainContentBackground = null!;
|
|
||||||
private FillFlowContainer<BeatmapCardStatistic> statisticsContainer = null!;
|
private FillFlowContainer<BeatmapCardStatistic> statisticsContainer = null!;
|
||||||
|
|
||||||
private FillFlowContainer idleBottomContent = null!;
|
private FillFlowContainer idleBottomContent = null!;
|
||||||
private BeatmapCardDownloadProgressBar downloadProgressBar = null!;
|
private BeatmapCardDownloadProgressBar downloadProgressBar = null!;
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private OsuColour colours { get; set; } = null!;
|
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private OverlayColourProvider colourProvider { get; set; } = null!;
|
private OverlayColourProvider colourProvider { get; set; } = null!;
|
||||||
|
|
||||||
public BeatmapCard(APIBeatmapSet beatmapSet, bool allowExpansion = true)
|
public BeatmapCard(APIBeatmapSet beatmapSet, bool allowExpansion = true)
|
||||||
: base(HoverSampleSet.Submit)
|
: base(beatmapSet, allowExpansion)
|
||||||
{
|
{
|
||||||
Expanded = new BindableBool { Disabled = !allowExpansion };
|
content = new BeatmapCardContent(height);
|
||||||
|
|
||||||
this.beatmapSet = beatmapSet;
|
|
||||||
favouriteState = new Bindable<BeatmapSetFavouriteState>(new BeatmapSetFavouriteState(beatmapSet.HasFavourited, beatmapSet.FavouriteCount));
|
|
||||||
downloadTracker = new BeatmapDownloadTracker(beatmapSet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader]
|
||||||
private void load(BeatmapSetOverlay? beatmapSetOverlay)
|
private void load()
|
||||||
{
|
{
|
||||||
Width = width;
|
Width = width;
|
||||||
Height = height;
|
Height = height;
|
||||||
|
|
||||||
FillFlowContainer leftIconArea;
|
FillFlowContainer leftIconArea = null!;
|
||||||
GridContainer titleContainer;
|
GridContainer titleContainer = null!;
|
||||||
GridContainer artistContainer;
|
GridContainer artistContainer = null!;
|
||||||
|
|
||||||
InternalChild = content = new BeatmapCardContent(height)
|
Child = content.With(c =>
|
||||||
{
|
{
|
||||||
MainContent = new Container
|
c.MainContent = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
downloadTracker,
|
thumbnail = new BeatmapCardThumbnail(BeatmapSet)
|
||||||
rightAreaBackground = new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
Width = icon_area_width + 2 * CORNER_RADIUS,
|
|
||||||
Anchor = Anchor.CentreRight,
|
|
||||||
Origin = Anchor.CentreRight,
|
|
||||||
// workaround for masking artifacts at the top & bottom of card,
|
|
||||||
// which become especially visible on downloaded beatmaps (when the icon area has a lime background).
|
|
||||||
Padding = new MarginPadding { Vertical = 1 },
|
|
||||||
Child = new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = Colour4.White
|
|
||||||
},
|
|
||||||
},
|
|
||||||
thumbnail = new BeatmapCardThumbnail(beatmapSet)
|
|
||||||
{
|
{
|
||||||
Name = @"Left (icon) area",
|
Name = @"Left (icon) area",
|
||||||
Size = new Vector2(height),
|
Size = new Vector2(height),
|
||||||
@ -120,61 +79,19 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
Spacing = new Vector2(1)
|
Spacing = new Vector2(1)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Container
|
buttonContainer = new CollapsibleButtonContainer(BeatmapSet)
|
||||||
{
|
{
|
||||||
Name = @"Right (button) area",
|
|
||||||
Width = 30,
|
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
Origin = Anchor.TopRight,
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Padding = new MarginPadding { Vertical = 17.5f },
|
|
||||||
Child = rightAreaButtons = new Container<BeatmapCardIconButton>
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Children = new BeatmapCardIconButton[]
|
|
||||||
{
|
|
||||||
new FavouriteButton(beatmapSet)
|
|
||||||
{
|
|
||||||
Current = favouriteState,
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre
|
|
||||||
},
|
|
||||||
new DownloadButton(beatmapSet)
|
|
||||||
{
|
|
||||||
Anchor = Anchor.BottomCentre,
|
|
||||||
Origin = Anchor.BottomCentre,
|
|
||||||
State = { BindTarget = downloadTracker.State }
|
|
||||||
},
|
|
||||||
new GoToBeatmapButton(beatmapSet)
|
|
||||||
{
|
|
||||||
Anchor = Anchor.BottomCentre,
|
|
||||||
Origin = Anchor.BottomCentre,
|
|
||||||
State = { BindTarget = downloadTracker.State }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mainContent = new Container
|
|
||||||
{
|
|
||||||
Name = @"Main content",
|
|
||||||
X = height - CORNER_RADIUS,
|
X = height - CORNER_RADIUS,
|
||||||
Height = height,
|
Width = width - height + CORNER_RADIUS,
|
||||||
CornerRadius = CORNER_RADIUS,
|
FavouriteState = { BindTarget = FavouriteState },
|
||||||
Masking = true,
|
ButtonsCollapsedWidth = CORNER_RADIUS,
|
||||||
|
ButtonsExpandedWidth = 30,
|
||||||
|
ButtonsPadding = new MarginPadding { Vertical = 17.5f },
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
mainContentBackground = new BeatmapCardContentBackground(beatmapSet)
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
},
|
|
||||||
new FillFlowContainer
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Padding = new MarginPadding
|
|
||||||
{
|
|
||||||
Horizontal = 10,
|
|
||||||
Vertical = 4
|
|
||||||
},
|
|
||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
@ -197,7 +114,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
{
|
{
|
||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
{
|
{
|
||||||
Text = new RomanisableString(beatmapSet.TitleUnicode, beatmapSet.Title),
|
Text = new RomanisableString(BeatmapSet.TitleUnicode, BeatmapSet.Title),
|
||||||
Font = OsuFont.Default.With(size: 22.5f, weight: FontWeight.SemiBold),
|
Font = OsuFont.Default.With(size: 22.5f, weight: FontWeight.SemiBold),
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Truncate = true
|
Truncate = true
|
||||||
@ -243,7 +160,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
d.AutoSizeAxes = Axes.Both;
|
d.AutoSizeAxes = Axes.Both;
|
||||||
d.Margin = new MarginPadding { Top = 2 };
|
d.Margin = new MarginPadding { Top = 2 };
|
||||||
d.AddText("mapped by ", t => t.Colour = colourProvider.Content2);
|
d.AddText("mapped by ", t => t.Colour = colourProvider.Content2);
|
||||||
d.AddUserLink(beatmapSet.Author);
|
d.AddUserLink(BeatmapSet.Author);
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -254,11 +171,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomLeft,
|
||||||
Origin = Anchor.BottomLeft,
|
Origin = Anchor.BottomLeft,
|
||||||
Padding = new MarginPadding
|
|
||||||
{
|
|
||||||
Horizontal = 10,
|
|
||||||
Vertical = 4
|
|
||||||
},
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
idleBottomContent = new FillFlowContainer
|
idleBottomContent = new FillFlowContainer
|
||||||
@ -280,21 +192,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
AlwaysPresent = true,
|
AlwaysPresent = true,
|
||||||
ChildrenEnumerable = createStatistics()
|
ChildrenEnumerable = createStatistics()
|
||||||
},
|
},
|
||||||
new BeatmapCardExtraInfoRow(beatmapSet)
|
new BeatmapCardExtraInfoRow(BeatmapSet)
|
||||||
{
|
|
||||||
Hovered = _ =>
|
|
||||||
{
|
|
||||||
content.ExpandAfterDelay();
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
Unhovered = _ =>
|
|
||||||
{
|
|
||||||
// Handles the case where a user has not shown explicit intent to view expanded info.
|
|
||||||
// ie. quickly moved over the info row area but didn't remain within it.
|
|
||||||
if (!Expanded.Value)
|
|
||||||
content.CancelExpand();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
downloadProgressBar = new BeatmapCardDownloadProgressBar
|
downloadProgressBar = new BeatmapCardDownloadProgressBar
|
||||||
@ -303,32 +201,32 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
Height = 6,
|
Height = 6,
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
State = { BindTarget = downloadTracker.State },
|
State = { BindTarget = DownloadTracker.State },
|
||||||
Progress = { BindTarget = downloadTracker.Progress }
|
Progress = { BindTarget = DownloadTracker.Progress }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
ExpandedContent = new Container
|
c.ExpandedContent = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Padding = new MarginPadding { Horizontal = 10, Vertical = 13 },
|
Padding = new MarginPadding { Horizontal = 10, Vertical = 13 },
|
||||||
Child = new BeatmapCardDifficultyList(beatmapSet)
|
Child = new BeatmapCardDifficultyList(BeatmapSet)
|
||||||
},
|
};
|
||||||
Expanded = { BindTarget = Expanded }
|
c.Expanded.BindTarget = Expanded;
|
||||||
};
|
});
|
||||||
|
|
||||||
if (beatmapSet.HasVideo)
|
if (BeatmapSet.HasVideo)
|
||||||
leftIconArea.Add(new IconPill(FontAwesome.Solid.Film) { IconSize = new Vector2(20) });
|
leftIconArea.Add(new IconPill(FontAwesome.Solid.Film) { IconSize = new Vector2(20) });
|
||||||
|
|
||||||
if (beatmapSet.HasStoryboard)
|
if (BeatmapSet.HasStoryboard)
|
||||||
leftIconArea.Add(new IconPill(FontAwesome.Solid.Image) { IconSize = new Vector2(20) });
|
leftIconArea.Add(new IconPill(FontAwesome.Solid.Image) { IconSize = new Vector2(20) });
|
||||||
|
|
||||||
if (beatmapSet.HasExplicitContent)
|
if (BeatmapSet.HasExplicitContent)
|
||||||
{
|
{
|
||||||
titleContainer.Content[0][1] = new ExplicitContentBeatmapPill
|
titleContainer.Content[0][1] = new ExplicitContentBeatmapPill
|
||||||
{
|
{
|
||||||
@ -338,7 +236,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (beatmapSet.TrackId != null)
|
if (BeatmapSet.TrackId != null)
|
||||||
{
|
{
|
||||||
artistContainer.Content[0][1] = new FeaturedArtistBeatmapPill
|
artistContainer.Content[0][1] = new FeaturedArtistBeatmapPill
|
||||||
{
|
{
|
||||||
@ -347,87 +245,42 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
Margin = new MarginPadding { Left = 5 }
|
Margin = new MarginPadding { Left = 5 }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Action = () => beatmapSetOverlay?.FetchAndShowBeatmapSet(beatmapSet.OnlineID);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
downloadTracker.State.BindValueChanged(_ => updateState());
|
|
||||||
Expanded.BindValueChanged(_ => updateState(), true);
|
|
||||||
FinishTransforms(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
|
||||||
{
|
|
||||||
updateState();
|
|
||||||
return base.OnHover(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnHoverLost(HoverLostEvent e)
|
|
||||||
{
|
|
||||||
updateState();
|
|
||||||
base.OnHoverLost(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalisableString createArtistText()
|
private LocalisableString createArtistText()
|
||||||
{
|
{
|
||||||
var romanisableArtist = new RomanisableString(beatmapSet.ArtistUnicode, beatmapSet.Artist);
|
var romanisableArtist = new RomanisableString(BeatmapSet.ArtistUnicode, BeatmapSet.Artist);
|
||||||
return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist);
|
return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<BeatmapCardStatistic> createStatistics()
|
private IEnumerable<BeatmapCardStatistic> createStatistics()
|
||||||
{
|
{
|
||||||
if (beatmapSet.HypeStatus != null)
|
var hypesStatistic = HypesStatistic.CreateFor(BeatmapSet);
|
||||||
yield return new HypesStatistic(beatmapSet.HypeStatus);
|
if (hypesStatistic != null)
|
||||||
|
yield return hypesStatistic;
|
||||||
|
|
||||||
// web does not show nominations unless hypes are also present.
|
var nominationsStatistic = NominationsStatistic.CreateFor(BeatmapSet);
|
||||||
// see: https://github.com/ppy/osu-web/blob/8ed7d071fd1d3eaa7e43cf0e4ff55ca2fef9c07c/resources/assets/lib/beatmapset-panel.tsx#L443
|
if (nominationsStatistic != null)
|
||||||
if (beatmapSet.HypeStatus != null && beatmapSet.NominationStatus != null)
|
yield return nominationsStatistic;
|
||||||
yield return new NominationsStatistic(beatmapSet.NominationStatus);
|
|
||||||
|
|
||||||
yield return new FavouritesStatistic(beatmapSet) { Current = favouriteState };
|
yield return new FavouritesStatistic(BeatmapSet) { Current = FavouriteState };
|
||||||
yield return new PlayCountStatistic(beatmapSet);
|
yield return new PlayCountStatistic(BeatmapSet);
|
||||||
|
|
||||||
var dateStatistic = BeatmapCardDateStatistic.CreateFor(beatmapSet);
|
var dateStatistic = BeatmapCardDateStatistic.CreateFor(BeatmapSet);
|
||||||
if (dateStatistic != null)
|
if (dateStatistic != null)
|
||||||
yield return dateStatistic;
|
yield return dateStatistic;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateState()
|
protected override void UpdateState()
|
||||||
{
|
{
|
||||||
|
base.UpdateState();
|
||||||
|
|
||||||
bool showDetails = IsHovered || Expanded.Value;
|
bool showDetails = IsHovered || Expanded.Value;
|
||||||
|
|
||||||
float targetWidth = width - height;
|
buttonContainer.ShowDetails.Value = showDetails;
|
||||||
if (showDetails)
|
|
||||||
targetWidth = targetWidth - icon_area_width + CORNER_RADIUS;
|
|
||||||
|
|
||||||
thumbnail.Dimmed.Value = showDetails;
|
thumbnail.Dimmed.Value = showDetails;
|
||||||
|
|
||||||
// Scale value is intentionally chosen to fit in the spacing of listing displays, as to not overlap horizontally with adjacent cards.
|
|
||||||
// This avoids depth issues where a hovered (scaled) card to the right of another card would be beneath the card to the left.
|
|
||||||
content.ScaleTo(Expanded.Value ? 1.03f : 1, 500, Easing.OutQuint);
|
|
||||||
|
|
||||||
mainContent.ResizeWidthTo(targetWidth, TRANSITION_DURATION, Easing.OutQuint);
|
|
||||||
mainContentBackground.Dimmed.Value = showDetails;
|
|
||||||
|
|
||||||
statisticsContainer.FadeTo(showDetails ? 1 : 0, TRANSITION_DURATION, Easing.OutQuint);
|
statisticsContainer.FadeTo(showDetails ? 1 : 0, TRANSITION_DURATION, Easing.OutQuint);
|
||||||
|
|
||||||
rightAreaBackground.FadeColour(downloadTracker.State.Value == DownloadState.LocallyAvailable ? colours.Lime0 : colourProvider.Background3, TRANSITION_DURATION, Easing.OutQuint);
|
|
||||||
rightAreaButtons.FadeTo(showDetails ? 1 : 0, TRANSITION_DURATION, Easing.OutQuint);
|
|
||||||
|
|
||||||
foreach (var button in rightAreaButtons)
|
|
||||||
{
|
|
||||||
button.IdleColour = downloadTracker.State.Value != DownloadState.LocallyAvailable ? colourProvider.Light1 : colourProvider.Background3;
|
|
||||||
button.HoverColour = downloadTracker.State.Value != DownloadState.LocallyAvailable ? colourProvider.Content1 : colourProvider.Foreground1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool showProgress = downloadTracker.State.Value == DownloadState.Downloading || downloadTracker.State.Value == DownloadState.Importing;
|
|
||||||
|
|
||||||
idleBottomContent.FadeTo(showProgress ? 0 : 1, TRANSITION_DURATION, Easing.OutQuint);
|
|
||||||
downloadProgressBar.FadeTo(showProgress ? 1 : 0, TRANSITION_DURATION, Easing.OutQuint);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
80
osu.Game/Beatmaps/Drawables/Cards/BeatmapCardBase.cs
Normal file
80
osu.Game/Beatmaps/Drawables/Cards/BeatmapCardBase.cs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// 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 enable
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Online;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
|
||||||
|
namespace osu.Game.Beatmaps.Drawables.Cards
|
||||||
|
{
|
||||||
|
public abstract class BeatmapCardBase : OsuClickableContainer
|
||||||
|
{
|
||||||
|
public const float TRANSITION_DURATION = 400;
|
||||||
|
public const float CORNER_RADIUS = 10;
|
||||||
|
|
||||||
|
public IBindable<bool> Expanded { get; }
|
||||||
|
|
||||||
|
protected readonly APIBeatmapSet BeatmapSet;
|
||||||
|
protected readonly Bindable<BeatmapSetFavouriteState> FavouriteState;
|
||||||
|
|
||||||
|
protected abstract Drawable IdleContent { get; }
|
||||||
|
protected abstract Drawable DownloadInProgressContent { get; }
|
||||||
|
|
||||||
|
protected readonly BeatmapDownloadTracker DownloadTracker;
|
||||||
|
|
||||||
|
protected BeatmapCardBase(APIBeatmapSet beatmapSet, bool allowExpansion = true)
|
||||||
|
: base(HoverSampleSet.Submit)
|
||||||
|
{
|
||||||
|
Expanded = new BindableBool { Disabled = !allowExpansion };
|
||||||
|
|
||||||
|
BeatmapSet = beatmapSet;
|
||||||
|
FavouriteState = new Bindable<BeatmapSetFavouriteState>(new BeatmapSetFavouriteState(beatmapSet.HasFavourited, beatmapSet.FavouriteCount));
|
||||||
|
DownloadTracker = new BeatmapDownloadTracker(beatmapSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load(BeatmapSetOverlay? beatmapSetOverlay)
|
||||||
|
{
|
||||||
|
Action = () => beatmapSetOverlay?.FetchAndShowBeatmapSet(BeatmapSet.OnlineID);
|
||||||
|
|
||||||
|
AddInternal(DownloadTracker);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
DownloadTracker.State.BindValueChanged(_ => UpdateState());
|
||||||
|
Expanded.BindValueChanged(_ => UpdateState(), true);
|
||||||
|
FinishTransforms(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
{
|
||||||
|
UpdateState();
|
||||||
|
return base.OnHover(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
|
{
|
||||||
|
UpdateState();
|
||||||
|
base.OnHoverLost(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdateState()
|
||||||
|
{
|
||||||
|
bool showProgress = DownloadTracker.State.Value == DownloadState.Downloading || DownloadTracker.State.Value == DownloadState.Importing;
|
||||||
|
|
||||||
|
IdleContent.FadeTo(showProgress ? 0 : 1, TRANSITION_DURATION, Easing.OutQuint);
|
||||||
|
DownloadInProgressContent.FadeTo(showProgress ? 1 : 0, TRANSITION_DURATION, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -54,7 +54,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
CornerRadius = BeatmapCard.CORNER_RADIUS,
|
CornerRadius = BeatmapCardBase.CORNER_RADIUS,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
Unhovered = _ => updateFromHoverChange(),
|
Unhovered = _ => updateFromHoverChange(),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
@ -67,7 +67,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = height,
|
Height = height,
|
||||||
CornerRadius = BeatmapCard.CORNER_RADIUS,
|
CornerRadius = BeatmapCardBase.CORNER_RADIUS,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
},
|
},
|
||||||
dropdownContent = new HoverHandlingContainer
|
dropdownContent = new HoverHandlingContainer
|
||||||
@ -91,7 +91,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
borderContainer = new Container
|
borderContainer = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
CornerRadius = BeatmapCard.CORNER_RADIUS,
|
CornerRadius = BeatmapCardBase.CORNER_RADIUS,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
BorderThickness = 3,
|
BorderThickness = 3,
|
||||||
Child = new Box
|
Child = new Box
|
||||||
@ -139,9 +139,13 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
|
|
||||||
private void updateState()
|
private void updateState()
|
||||||
{
|
{
|
||||||
background.FadeTo(Expanded.Value ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
|
// Scale value is intentionally chosen to fit in the spacing of listing displays, as to not overlap horizontally with adjacent cards.
|
||||||
dropdownContent.FadeTo(Expanded.Value ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
|
// This avoids depth issues where a hovered (scaled) card to the right of another card would be beneath the card to the left.
|
||||||
borderContainer.FadeTo(Expanded.Value ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
|
this.ScaleTo(Expanded.Value ? 1.03f : 1, 500, Easing.OutQuint);
|
||||||
|
|
||||||
|
background.FadeTo(Expanded.Value ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
|
dropdownContent.FadeTo(Expanded.Value ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
|
borderContainer.FadeTo(Expanded.Value ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
|
|
||||||
content.TweenEdgeEffectTo(new EdgeEffectParameters
|
content.TweenEdgeEffectTo(new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
@ -150,7 +154,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
Radius = 10,
|
Radius = 10,
|
||||||
Colour = Colour4.Black.Opacity(Expanded.Value ? 0.3f : 0f),
|
Colour = Colour4.Black.Opacity(Expanded.Value ? 0.3f : 0f),
|
||||||
Hollow = true,
|
Hollow = true,
|
||||||
}, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
|
}, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ExpandedContentScrollContainer : OsuScrollContainer
|
private class ExpandedContentScrollContainer : OsuScrollContainer
|
||||||
|
@ -62,10 +62,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
|
|
||||||
private void updateState() => Schedule(() =>
|
private void updateState() => Schedule(() =>
|
||||||
{
|
{
|
||||||
background.FadeColour(Dimmed.Value ? colourProvider.Background4 : colourProvider.Background2, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
|
background.FadeColour(Dimmed.Value ? colourProvider.Background4 : colourProvider.Background2, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
|
|
||||||
var gradient = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0), Colour4.White.Opacity(0.2f));
|
var gradient = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0), Colour4.White.Opacity(0.2f));
|
||||||
cover.FadeColour(gradient, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
|
cover.FadeColour(gradient, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,14 +82,14 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DownloadState.Importing:
|
case DownloadState.Importing:
|
||||||
foregroundFill.FadeColour(colours.Yellow, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
|
foregroundFill.FadeColour(colours.Yellow, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void progressChanged()
|
private void progressChanged()
|
||||||
{
|
{
|
||||||
foreground.ResizeWidthTo((float)progress.Value, progress.Value > 0 ? BeatmapCard.TRANSITION_DURATION : 0, Easing.OutQuint);
|
foreground.ResizeWidthTo((float)progress.Value, progress.Value > 0 ? BeatmapCardBase.TRANSITION_DURATION : 0, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
317
osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs
Normal file
317
osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
// 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 enable
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Beatmaps.Drawables.Cards.Statistics;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Overlays.BeatmapSet;
|
||||||
|
using osuTK;
|
||||||
|
using osu.Game.Resources.Localisation.Web;
|
||||||
|
|
||||||
|
namespace osu.Game.Beatmaps.Drawables.Cards
|
||||||
|
{
|
||||||
|
public class BeatmapCardExtra : BeatmapCardBase
|
||||||
|
{
|
||||||
|
protected override Drawable IdleContent => idleBottomContent;
|
||||||
|
protected override Drawable DownloadInProgressContent => downloadProgressBar;
|
||||||
|
|
||||||
|
private const float width = 475;
|
||||||
|
private const float height = 140;
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly BeatmapCardContent content;
|
||||||
|
|
||||||
|
private BeatmapCardThumbnail thumbnail = null!;
|
||||||
|
private CollapsibleButtonContainer buttonContainer = null!;
|
||||||
|
|
||||||
|
private GridContainer statisticsContainer = null!;
|
||||||
|
|
||||||
|
private FillFlowContainer idleBottomContent = null!;
|
||||||
|
private BeatmapCardDownloadProgressBar downloadProgressBar = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OverlayColourProvider colourProvider { get; set; } = null!;
|
||||||
|
|
||||||
|
public BeatmapCardExtra(APIBeatmapSet beatmapSet, bool allowExpansion = true)
|
||||||
|
: base(beatmapSet, allowExpansion)
|
||||||
|
{
|
||||||
|
content = new BeatmapCardContent(height);
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load(BeatmapSetOverlay? beatmapSetOverlay)
|
||||||
|
{
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
|
||||||
|
FillFlowContainer leftIconArea = null!;
|
||||||
|
GridContainer titleContainer = null!;
|
||||||
|
GridContainer artistContainer = null!;
|
||||||
|
|
||||||
|
Child = content.With(c =>
|
||||||
|
{
|
||||||
|
c.MainContent = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
thumbnail = new BeatmapCardThumbnail(BeatmapSet)
|
||||||
|
{
|
||||||
|
Name = @"Left (icon) area",
|
||||||
|
Size = new Vector2(height),
|
||||||
|
Padding = new MarginPadding { Right = CORNER_RADIUS },
|
||||||
|
Child = leftIconArea = new FillFlowContainer
|
||||||
|
{
|
||||||
|
Margin = new MarginPadding(5),
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Spacing = new Vector2(1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buttonContainer = new CollapsibleButtonContainer(BeatmapSet)
|
||||||
|
{
|
||||||
|
X = height - CORNER_RADIUS,
|
||||||
|
Width = width - height + CORNER_RADIUS,
|
||||||
|
FavouriteState = { BindTarget = FavouriteState },
|
||||||
|
ButtonsCollapsedWidth = CORNER_RADIUS,
|
||||||
|
ButtonsExpandedWidth = 30,
|
||||||
|
ButtonsPadding = new MarginPadding { Vertical = 35 },
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
titleContainer = new GridContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
ColumnDimensions = new[]
|
||||||
|
{
|
||||||
|
new Dimension(),
|
||||||
|
new Dimension(GridSizeMode.AutoSize)
|
||||||
|
},
|
||||||
|
RowDimensions = new[]
|
||||||
|
{
|
||||||
|
new Dimension(GridSizeMode.AutoSize)
|
||||||
|
},
|
||||||
|
Content = new[]
|
||||||
|
{
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Text = new RomanisableString(BeatmapSet.TitleUnicode, BeatmapSet.Title),
|
||||||
|
Font = OsuFont.Default.With(size: 22.5f, weight: FontWeight.SemiBold),
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Truncate = true
|
||||||
|
},
|
||||||
|
Empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
artistContainer = new GridContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
ColumnDimensions = new[]
|
||||||
|
{
|
||||||
|
new Dimension(),
|
||||||
|
new Dimension(GridSizeMode.AutoSize)
|
||||||
|
},
|
||||||
|
RowDimensions = new[]
|
||||||
|
{
|
||||||
|
new Dimension(GridSizeMode.AutoSize)
|
||||||
|
},
|
||||||
|
Content = new[]
|
||||||
|
{
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Text = createArtistText(),
|
||||||
|
Font = OsuFont.Default.With(size: 17.5f, weight: FontWeight.SemiBold),
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Truncate = true
|
||||||
|
},
|
||||||
|
Empty()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Truncate = true,
|
||||||
|
Text = BeatmapSet.Source,
|
||||||
|
Shadow = false,
|
||||||
|
Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold),
|
||||||
|
Colour = colourProvider.Content2
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Name = @"Bottom content",
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
idleBottomContent = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(0, 3),
|
||||||
|
AlwaysPresent = true,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new LinkFlowContainer(s =>
|
||||||
|
{
|
||||||
|
s.Shadow = false;
|
||||||
|
s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold);
|
||||||
|
}).With(d =>
|
||||||
|
{
|
||||||
|
d.AutoSizeAxes = Axes.Both;
|
||||||
|
d.Margin = new MarginPadding { Top = 2 };
|
||||||
|
d.AddText("mapped by ", t => t.Colour = colourProvider.Content2);
|
||||||
|
d.AddUserLink(BeatmapSet.Author);
|
||||||
|
}),
|
||||||
|
statisticsContainer = new GridContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
RowDimensions = new[]
|
||||||
|
{
|
||||||
|
new Dimension(GridSizeMode.AutoSize),
|
||||||
|
new Dimension(GridSizeMode.AutoSize)
|
||||||
|
},
|
||||||
|
ColumnDimensions = new[]
|
||||||
|
{
|
||||||
|
new Dimension(GridSizeMode.AutoSize),
|
||||||
|
new Dimension(GridSizeMode.AutoSize),
|
||||||
|
new Dimension()
|
||||||
|
},
|
||||||
|
Content = new[]
|
||||||
|
{
|
||||||
|
new Drawable[3],
|
||||||
|
new Drawable[3]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new BeatmapCardExtraInfoRow(BeatmapSet)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
downloadProgressBar = new BeatmapCardDownloadProgressBar
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 6,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
State = { BindTarget = DownloadTracker.State },
|
||||||
|
Progress = { BindTarget = DownloadTracker.Progress }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
c.ExpandedContent = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Padding = new MarginPadding { Horizontal = 10, Vertical = 13 },
|
||||||
|
Child = new BeatmapCardDifficultyList(BeatmapSet)
|
||||||
|
};
|
||||||
|
c.Expanded.BindTarget = Expanded;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (BeatmapSet.HasVideo)
|
||||||
|
leftIconArea.Add(new IconPill(FontAwesome.Solid.Film) { IconSize = new Vector2(20) });
|
||||||
|
|
||||||
|
if (BeatmapSet.HasStoryboard)
|
||||||
|
leftIconArea.Add(new IconPill(FontAwesome.Solid.Image) { IconSize = new Vector2(20) });
|
||||||
|
|
||||||
|
if (BeatmapSet.HasExplicitContent)
|
||||||
|
{
|
||||||
|
titleContainer.Content[0][1] = new ExplicitContentBeatmapPill
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomRight,
|
||||||
|
Origin = Anchor.BottomRight,
|
||||||
|
Margin = new MarginPadding { Left = 5 }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BeatmapSet.TrackId != null)
|
||||||
|
{
|
||||||
|
artistContainer.Content[0][1] = new FeaturedArtistBeatmapPill
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomRight,
|
||||||
|
Origin = Anchor.BottomRight,
|
||||||
|
Margin = new MarginPadding { Left = 5 }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
createStatistics();
|
||||||
|
|
||||||
|
Action = () => beatmapSetOverlay?.FetchAndShowBeatmapSet(BeatmapSet.OnlineID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalisableString createArtistText()
|
||||||
|
{
|
||||||
|
var romanisableArtist = new RomanisableString(BeatmapSet.ArtistUnicode, BeatmapSet.Artist);
|
||||||
|
return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createStatistics()
|
||||||
|
{
|
||||||
|
BeatmapCardStatistic withMargin(BeatmapCardStatistic original)
|
||||||
|
{
|
||||||
|
original.Margin = new MarginPadding { Right = 10 };
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
|
||||||
|
statisticsContainer.Content[0][0] = withMargin(new FavouritesStatistic(BeatmapSet)
|
||||||
|
{
|
||||||
|
Current = FavouriteState,
|
||||||
|
});
|
||||||
|
|
||||||
|
statisticsContainer.Content[1][0] = withMargin(new PlayCountStatistic(BeatmapSet));
|
||||||
|
|
||||||
|
var hypesStatistic = HypesStatistic.CreateFor(BeatmapSet);
|
||||||
|
if (hypesStatistic != null)
|
||||||
|
statisticsContainer.Content[0][1] = withMargin(hypesStatistic);
|
||||||
|
|
||||||
|
var nominationsStatistic = NominationsStatistic.CreateFor(BeatmapSet);
|
||||||
|
if (nominationsStatistic != null)
|
||||||
|
statisticsContainer.Content[1][1] = withMargin(nominationsStatistic);
|
||||||
|
|
||||||
|
var dateStatistic = BeatmapCardDateStatistic.CreateFor(BeatmapSet);
|
||||||
|
if (dateStatistic != null)
|
||||||
|
statisticsContainer.Content[0][2] = withMargin(dateStatistic);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateState()
|
||||||
|
{
|
||||||
|
base.UpdateState();
|
||||||
|
|
||||||
|
bool showDetails = IsHovered || Expanded.Value;
|
||||||
|
|
||||||
|
buttonContainer.ShowDetails.Value = showDetails;
|
||||||
|
thumbnail.Dimmed.Value = showDetails;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,21 +1,28 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps.Drawables.Cards
|
namespace osu.Game.Beatmaps.Drawables.Cards
|
||||||
{
|
{
|
||||||
public class BeatmapCardExtraInfoRow : HoverHandlingContainer
|
public class BeatmapCardExtraInfoRow : CompositeDrawable
|
||||||
{
|
{
|
||||||
|
[Resolved(CanBeNull = true)]
|
||||||
|
private BeatmapCardContent? content { get; set; }
|
||||||
|
|
||||||
public BeatmapCardExtraInfoRow(APIBeatmapSet beatmapSet)
|
public BeatmapCardExtraInfoRow(APIBeatmapSet beatmapSet)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
AutoSizeAxes = Axes.Y;
|
AutoSizeAxes = Axes.Y;
|
||||||
|
|
||||||
Child = new FillFlowContainer
|
InternalChild = new FillFlowContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
@ -39,5 +46,19 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
{
|
||||||
|
content?.ExpandAfterDelay();
|
||||||
|
return base.OnHover(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
|
{
|
||||||
|
if (content?.Expanded.Value == false)
|
||||||
|
content.CancelExpand();
|
||||||
|
|
||||||
|
base.OnHoverLost(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,8 +88,8 @@ namespace osu.Game.Beatmaps.Drawables.Cards
|
|||||||
{
|
{
|
||||||
bool shouldDim = Dimmed.Value || playButton.Playing.Value;
|
bool shouldDim = Dimmed.Value || playButton.Playing.Value;
|
||||||
|
|
||||||
playButton.FadeTo(shouldDim ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
|
playButton.FadeTo(shouldDim ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
cover.FadeColour(shouldDim ? OsuColour.Gray(0.2f) : Color4.White, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
|
cover.FadeColour(shouldDim ? OsuColour.Gray(0.2f) : Color4.White, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
|
|||||||
bool isHovered = IsHovered && Enabled.Value;
|
bool isHovered = IsHovered && Enabled.Value;
|
||||||
|
|
||||||
content.ScaleTo(isHovered ? 1.2f : 1, 500, Easing.OutQuint);
|
content.ScaleTo(isHovered ? 1.2f : 1, 500, Easing.OutQuint);
|
||||||
content.FadeColour(isHovered ? HoverColour : IdleColour, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
|
content.FadeColour(isHovered ? HoverColour : IdleColour, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
|
|||||||
case DownloadState.LocallyAvailable:
|
case DownloadState.LocallyAvailable:
|
||||||
Action = null;
|
Action = null;
|
||||||
TooltipText = string.Empty;
|
TooltipText = string.Empty;
|
||||||
this.FadeOut(BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
|
this.FadeOut(BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DownloadState.NotDownloaded:
|
case DownloadState.NotDownloaded:
|
||||||
@ -81,7 +81,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
|
|||||||
}
|
}
|
||||||
|
|
||||||
Action = () => beatmaps.Download(beatmapSet, preferNoVideo.Value);
|
Action = () => beatmaps.Download(beatmapSet, preferNoVideo.Value);
|
||||||
this.FadeIn(BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
|
this.FadeIn(BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
spinner.Hide();
|
spinner.Hide();
|
||||||
Icon.Show();
|
Icon.Show();
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
|
|||||||
|
|
||||||
private void updateState()
|
private void updateState()
|
||||||
{
|
{
|
||||||
this.FadeTo(state.Value == DownloadState.LocallyAvailable ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
|
this.FadeTo(state.Value == DownloadState.LocallyAvailable ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
|
|||||||
private void toggleLoading(bool loading)
|
private void toggleLoading(bool loading)
|
||||||
{
|
{
|
||||||
Enabled.Value = !loading;
|
Enabled.Value = !loading;
|
||||||
icon.FadeTo(loading ? 0 : 1, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint);
|
icon.FadeTo(loading ? 0 : 1, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
loadingSpinner.State.Value = loading ? Visibility.Visible : Visibility.Hidden;
|
loadingSpinner.State.Value = loading ? Visibility.Visible : Visibility.Hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
184
osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs
Normal file
184
osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
// 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 enable
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Beatmaps.Drawables.Cards.Buttons;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Online;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
|
||||||
|
namespace osu.Game.Beatmaps.Drawables.Cards
|
||||||
|
{
|
||||||
|
public class CollapsibleButtonContainer : Container
|
||||||
|
{
|
||||||
|
public Bindable<bool> ShowDetails = new Bindable<bool>();
|
||||||
|
public Bindable<BeatmapSetFavouriteState> FavouriteState = new Bindable<BeatmapSetFavouriteState>();
|
||||||
|
|
||||||
|
private readonly BeatmapDownloadTracker downloadTracker;
|
||||||
|
|
||||||
|
private float buttonsExpandedWidth;
|
||||||
|
|
||||||
|
public float ButtonsExpandedWidth
|
||||||
|
{
|
||||||
|
get => buttonsExpandedWidth;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
buttonsExpandedWidth = value;
|
||||||
|
buttonArea.Width = value;
|
||||||
|
if (IsLoaded)
|
||||||
|
updateState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float buttonsCollapsedWidth;
|
||||||
|
|
||||||
|
public float ButtonsCollapsedWidth
|
||||||
|
{
|
||||||
|
get => buttonsCollapsedWidth;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
buttonsCollapsedWidth = value;
|
||||||
|
if (IsLoaded)
|
||||||
|
updateState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MarginPadding ButtonsPadding
|
||||||
|
{
|
||||||
|
get => buttons.Padding;
|
||||||
|
set => buttons.Padding = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Container<Drawable> Content => mainContent;
|
||||||
|
|
||||||
|
private readonly Container background;
|
||||||
|
|
||||||
|
private readonly Container buttonArea;
|
||||||
|
private readonly Container<BeatmapCardIconButton> buttons;
|
||||||
|
|
||||||
|
private readonly Container mainArea;
|
||||||
|
private readonly Container mainContent;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuColour colours { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OverlayColourProvider colourProvider { get; set; } = null!;
|
||||||
|
|
||||||
|
public CollapsibleButtonContainer(APIBeatmapSet beatmapSet)
|
||||||
|
{
|
||||||
|
downloadTracker = new BeatmapDownloadTracker(beatmapSet);
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
Masking = true;
|
||||||
|
CornerRadius = BeatmapCardBase.CORNER_RADIUS;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
downloadTracker,
|
||||||
|
background = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
// workaround for masking artifacts at the top & bottom of card,
|
||||||
|
// which become especially visible on downloaded beatmaps (when the icon area has a lime background).
|
||||||
|
Padding = new MarginPadding { Vertical = 1 },
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Colour4.White
|
||||||
|
},
|
||||||
|
},
|
||||||
|
buttonArea = new Container
|
||||||
|
{
|
||||||
|
Name = @"Right (button) area",
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Child = buttons = new Container<BeatmapCardIconButton>
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Children = new BeatmapCardIconButton[]
|
||||||
|
{
|
||||||
|
new FavouriteButton(beatmapSet)
|
||||||
|
{
|
||||||
|
Current = FavouriteState,
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre
|
||||||
|
},
|
||||||
|
new DownloadButton(beatmapSet)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomCentre,
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
State = { BindTarget = downloadTracker.State }
|
||||||
|
},
|
||||||
|
new GoToBeatmapButton(beatmapSet)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomCentre,
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
State = { BindTarget = downloadTracker.State }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mainArea = new Container
|
||||||
|
{
|
||||||
|
Name = @"Main content",
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
CornerRadius = BeatmapCardBase.CORNER_RADIUS,
|
||||||
|
Masking = true,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new BeatmapCardContentBackground(beatmapSet)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Dimmed = { BindTarget = ShowDetails }
|
||||||
|
},
|
||||||
|
mainContent = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding
|
||||||
|
{
|
||||||
|
Horizontal = 10,
|
||||||
|
Vertical = 4
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
downloadTracker.State.BindValueChanged(_ => updateState());
|
||||||
|
ShowDetails.BindValueChanged(_ => updateState(), true);
|
||||||
|
FinishTransforms(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateState()
|
||||||
|
{
|
||||||
|
float targetWidth = Width - (ShowDetails.Value ? ButtonsExpandedWidth : ButtonsCollapsedWidth);
|
||||||
|
|
||||||
|
mainArea.ResizeWidthTo(targetWidth, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
|
|
||||||
|
background.FadeColour(downloadTracker.State.Value == DownloadState.LocallyAvailable ? colours.Lime0 : colourProvider.Background3, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
|
buttons.FadeTo(ShowDetails.Value ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint);
|
||||||
|
|
||||||
|
foreach (var button in buttons)
|
||||||
|
{
|
||||||
|
button.IdleColour = downloadTracker.State.Value != DownloadState.LocallyAvailable ? colourProvider.Light1 : colourProvider.Background3;
|
||||||
|
button.HoverColour = downloadTracker.State.Value != DownloadState.LocallyAvailable ? colourProvider.Content1 : colourProvider.Foreground1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
using osu.Framework.Extensions.LocalisationExtensions;
|
using osu.Framework.Extensions.LocalisationExtensions;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Resources.Localisation.Web;
|
using osu.Game.Resources.Localisation.Web;
|
||||||
@ -12,11 +14,14 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Statistics
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class HypesStatistic : BeatmapCardStatistic
|
public class HypesStatistic : BeatmapCardStatistic
|
||||||
{
|
{
|
||||||
public HypesStatistic(BeatmapSetHypeStatus hypeStatus)
|
private HypesStatistic(BeatmapSetHypeStatus hypeStatus)
|
||||||
{
|
{
|
||||||
Icon = FontAwesome.Solid.Bullhorn;
|
Icon = FontAwesome.Solid.Bullhorn;
|
||||||
Text = hypeStatus.Current.ToLocalisableString();
|
Text = hypeStatus.Current.ToLocalisableString();
|
||||||
TooltipText = BeatmapsStrings.HypeRequiredText(hypeStatus.Current.ToLocalisableString(), hypeStatus.Required.ToLocalisableString());
|
TooltipText = BeatmapsStrings.HypeRequiredText(hypeStatus.Current.ToLocalisableString(), hypeStatus.Required.ToLocalisableString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static HypesStatistic? CreateFor(IBeatmapSetOnlineInfo beatmapSetOnlineInfo)
|
||||||
|
=> beatmapSetOnlineInfo.HypeStatus == null ? null : new HypesStatistic(beatmapSetOnlineInfo.HypeStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
using osu.Framework.Extensions.LocalisationExtensions;
|
using osu.Framework.Extensions.LocalisationExtensions;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Resources.Localisation.Web;
|
using osu.Game.Resources.Localisation.Web;
|
||||||
@ -12,11 +14,16 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Statistics
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class NominationsStatistic : BeatmapCardStatistic
|
public class NominationsStatistic : BeatmapCardStatistic
|
||||||
{
|
{
|
||||||
public NominationsStatistic(BeatmapSetNominationStatus nominationStatus)
|
private NominationsStatistic(BeatmapSetNominationStatus nominationStatus)
|
||||||
{
|
{
|
||||||
Icon = FontAwesome.Solid.ThumbsUp;
|
Icon = FontAwesome.Solid.ThumbsUp;
|
||||||
Text = nominationStatus.Current.ToLocalisableString();
|
Text = nominationStatus.Current.ToLocalisableString();
|
||||||
TooltipText = BeatmapsStrings.NominationsRequiredText(nominationStatus.Current.ToLocalisableString(), nominationStatus.Required.ToLocalisableString());
|
TooltipText = BeatmapsStrings.NominationsRequiredText(nominationStatus.Current.ToLocalisableString(), nominationStatus.Required.ToLocalisableString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static NominationsStatistic? CreateFor(IBeatmapSetOnlineInfo beatmapSetOnlineInfo)
|
||||||
|
// web does not show nominations unless hypes are also present.
|
||||||
|
// see: https://github.com/ppy/osu-web/blob/8ed7d071fd1d3eaa7e43cf0e4ff55ca2fef9c07c/resources/assets/lib/beatmapset-panel.tsx#L443
|
||||||
|
=> beatmapSetOnlineInfo.HypeStatus == null || beatmapSetOnlineInfo.NominationStatus == null ? null : new NominationsStatistic(beatmapSetOnlineInfo.NominationStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user