Merge branch 'master' into volume-metre-keyboard-fix

This commit is contained in:
Bartłomiej Dach
2022-06-06 23:45:42 +02:00
committed by GitHub
56 changed files with 473 additions and 244 deletions

View File

@ -52,7 +52,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.527.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.603.1" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.605.0" />
</ItemGroup>
<ItemGroup Label="Transitive Dependencies">
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->

View File

@ -78,7 +78,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
}
});
if (!(source.FindProvider(s => s.GetTexture("spinner-top") != null) is DefaultLegacySkin))
var topProvider = source.FindProvider(s => s.GetTexture("spinner-top") != null);
if (topProvider is LegacySkinTransformer transformer && !(transformer.Skin is DefaultLegacySkin))
{
AddInternal(ApproachCircle = new Sprite
{

View File

@ -59,12 +59,14 @@ namespace osu.Game.Tests.Gameplay
scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new TestJudgement(HitResult.Great)) { Type = HitResult.Great });
Assert.That(scoreProcessor.TotalScore.Value, Is.EqualTo(1_000_000));
Assert.That(scoreProcessor.JudgedHits, Is.EqualTo(1));
Assert.That(scoreProcessor.Combo.Value, Is.EqualTo(1));
// No header shouldn't cause any change
scoreProcessor.ResetFromReplayFrame(new OsuReplayFrame());
Assert.That(scoreProcessor.TotalScore.Value, Is.EqualTo(1_000_000));
Assert.That(scoreProcessor.JudgedHits, Is.EqualTo(1));
Assert.That(scoreProcessor.Combo.Value, Is.EqualTo(1));
// Reset with a miss instead.
scoreProcessor.ResetFromReplayFrame(new OsuReplayFrame
@ -74,6 +76,7 @@ namespace osu.Game.Tests.Gameplay
Assert.That(scoreProcessor.TotalScore.Value, Is.Zero);
Assert.That(scoreProcessor.JudgedHits, Is.EqualTo(1));
Assert.That(scoreProcessor.Combo.Value, Is.EqualTo(0));
// Reset with no judged hit.
scoreProcessor.ResetFromReplayFrame(new OsuReplayFrame
@ -83,6 +86,7 @@ namespace osu.Game.Tests.Gameplay
Assert.That(scoreProcessor.TotalScore.Value, Is.Zero);
Assert.That(scoreProcessor.JudgedHits, Is.Zero);
Assert.That(scoreProcessor.Combo.Value, Is.EqualTo(0));
}
private class TestJudgement : Judgement

View File

@ -0,0 +1,48 @@
// 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 NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Utils;
namespace osu.Game.Tests.Visual.Editing
{
public class TestSceneTimelineZoom : TimelineTestScene
{
public override Drawable CreateTestComponent() => Empty();
[Test]
public void TestVisibleRangeUpdatesOnZoomChange()
{
double initialVisibleRange = 0;
AddStep("reset zoom", () => TimelineArea.Timeline.Zoom = 100);
AddStep("get initial range", () => initialVisibleRange = TimelineArea.Timeline.VisibleRange);
AddStep("scale zoom", () => TimelineArea.Timeline.Zoom = 200);
AddAssert("range halved", () => Precision.AlmostEquals(TimelineArea.Timeline.VisibleRange, initialVisibleRange / 2, 1));
AddStep("descale zoom", () => TimelineArea.Timeline.Zoom = 50);
AddAssert("range doubled", () => Precision.AlmostEquals(TimelineArea.Timeline.VisibleRange, initialVisibleRange * 2, 1));
AddStep("restore zoom", () => TimelineArea.Timeline.Zoom = 100);
AddAssert("range restored", () => Precision.AlmostEquals(TimelineArea.Timeline.VisibleRange, initialVisibleRange, 1));
}
[Test]
public void TestVisibleRangeConstantOnSizeChange()
{
double initialVisibleRange = 0;
AddStep("reset timeline size", () => TimelineArea.Timeline.Width = 1);
AddStep("get initial range", () => initialVisibleRange = TimelineArea.Timeline.VisibleRange);
AddStep("scale timeline size", () => TimelineArea.Timeline.Width = 2);
AddAssert("same range", () => TimelineArea.Timeline.VisibleRange == initialVisibleRange);
AddStep("descale timeline size", () => TimelineArea.Timeline.Width = 0.5f);
AddAssert("same range", () => TimelineArea.Timeline.VisibleRange == initialVisibleRange);
AddStep("restore timeline size", () => TimelineArea.Timeline.Width = 1);
AddAssert("same range", () => TimelineArea.Timeline.VisibleRange == initialVisibleRange);
}
}
}

View File

@ -44,7 +44,12 @@ namespace osu.Game.Tests.Visual.Editing
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.Gray(30)
},
scrollContainer = new ZoomableScrollContainer { RelativeSizeAxes = Axes.Both }
scrollContainer = new ZoomableScrollContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
}
}
},
new MenuCursor()
@ -62,7 +67,15 @@ namespace osu.Game.Tests.Visual.Editing
[Test]
public void TestWidthInitialization()
{
AddAssert("Inner container width was initialized", () => innerBox.DrawWidth > 0);
AddAssert("Inner container width was initialized", () => innerBox.DrawWidth == scrollContainer.DrawWidth);
}
[Test]
public void TestWidthUpdatesOnDrawSizeChanges()
{
AddStep("Shrink scroll container", () => scrollContainer.Width = 0.5f);
AddAssert("Scroll container width shrunk", () => scrollContainer.DrawWidth == scrollContainer.Parent.DrawWidth / 2);
AddAssert("Inner container width matches scroll container", () => innerBox.DrawWidth == scrollContainer.DrawWidth);
}
[Test]

View File

@ -128,11 +128,11 @@ namespace osu.Game.Tests.Visual.Online
AddAssert("Ensure no adjacent day separators", () =>
{
var indices = chatDisplay.FillFlow.OfType<DrawableChannel.DaySeparator>().Select(ds => chatDisplay.FillFlow.IndexOf(ds));
var indices = chatDisplay.FillFlow.OfType<DaySeparator>().Select(ds => chatDisplay.FillFlow.IndexOf(ds));
foreach (int i in indices)
{
if (i < chatDisplay.FillFlow.Count && chatDisplay.FillFlow[i + 1] is DrawableChannel.DaySeparator)
if (i < chatDisplay.FillFlow.Count && chatDisplay.FillFlow[i + 1] is DaySeparator)
return false;
}

View File

@ -319,6 +319,15 @@ namespace osu.Game.Beatmaps
});
}
public void DeleteAllVideos()
{
realm.Write(r =>
{
var items = r.All<BeatmapSetInfo>().Where(s => !s.DeletePending && !s.Protected);
beatmapModelManager.DeleteVideos(items.ToList());
});
}
public void UndeleteAll()
{
realm.Run(r => beatmapModelManager.Undelete(r.All<BeatmapSetInfo>().Where(s => s.DeletePending).ToList()));

View File

@ -16,6 +16,7 @@ using osu.Game.Database;
using osu.Game.Extensions;
using osu.Game.Skinning;
using osu.Game.Stores;
using osu.Game.Overlays.Notifications;
#nullable enable
@ -33,6 +34,8 @@ namespace osu.Game.Beatmaps
protected override string[] HashableFileTypes => new[] { ".osu" };
public static readonly string[] VIDEO_EXTENSIONS = { ".mp4", ".mov", ".avi", ".flv" };
public BeatmapModelManager(RealmAccess realm, Storage storage, BeatmapOnlineLookupQueue? onlineLookupQueue = null)
: base(realm, storage, onlineLookupQueue)
{
@ -114,5 +117,50 @@ namespace osu.Game.Beatmaps
item.CopyChangesToRealm(existing);
});
}
/// <summary>
/// Delete videos from a list of beatmaps.
/// This will post notifications tracking progress.
/// </summary>
public void DeleteVideos(List<BeatmapSetInfo> items, bool silent = false)
{
if (items.Count == 0) return;
var notification = new ProgressNotification
{
Progress = 0,
Text = $"Preparing to delete all {HumanisedModelName} videos...",
CompletionText = "No videos found to delete!",
State = ProgressNotificationState.Active,
};
if (!silent)
PostNotification?.Invoke(notification);
int i = 0;
int deleted = 0;
foreach (var b in items)
{
if (notification.State == ProgressNotificationState.Cancelled)
// user requested abort
return;
var video = b.Files.FirstOrDefault(f => VIDEO_EXTENSIONS.Any(ex => f.Filename.EndsWith(ex, StringComparison.Ordinal)));
if (video != null)
{
DeleteFile(b, video);
deleted++;
notification.CompletionText = $"Deleted {deleted} {HumanisedModelName} video(s)!";
}
notification.Text = $"Deleting videos from {HumanisedModelName}s ({deleted} deleted)";
notification.Progress = (float)++i / items.Count;
}
notification.State = ProgressNotificationState.Completed;
}
}
}

View File

@ -35,7 +35,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
protected readonly BeatmapDownloadTracker DownloadTracker;
protected BeatmapCard(APIBeatmapSet beatmapSet, bool allowExpansion = true)
: base(HoverSampleSet.Submit)
: base(HoverSampleSet.Button)
{
Expanded = new BindableBool { Disabled = !allowExpansion };

View File

@ -6,7 +6,6 @@
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;
@ -245,10 +244,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards
});
if (BeatmapSet.HasVideo)
leftIconArea.Add(new IconPill(FontAwesome.Solid.Film) { IconSize = new Vector2(20) });
leftIconArea.Add(new VideoIconPill { IconSize = new Vector2(20) });
if (BeatmapSet.HasStoryboard)
leftIconArea.Add(new IconPill(FontAwesome.Solid.Image) { IconSize = new Vector2(20) });
leftIconArea.Add(new StoryboardIconPill { IconSize = new Vector2(20) });
if (BeatmapSet.FeaturedInSpotlight)
{

View File

@ -7,7 +7,6 @@ using System.Collections.Generic;
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;
@ -226,10 +225,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards
});
if (BeatmapSet.HasVideo)
leftIconArea.Add(new IconPill(FontAwesome.Solid.Film) { IconSize = new Vector2(20) });
leftIconArea.Add(new VideoIconPill { IconSize = new Vector2(20) });
if (BeatmapSet.HasStoryboard)
leftIconArea.Add(new IconPill(FontAwesome.Solid.Image) { IconSize = new Vector2(20) });
leftIconArea.Add(new StoryboardIconPill { IconSize = new Vector2(20) });
if (BeatmapSet.FeaturedInSpotlight)
{

View File

@ -3,14 +3,16 @@
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Beatmaps.Drawables.Cards
{
public class IconPill : CircularContainer
public abstract class IconPill : CircularContainer, IHasTooltip
{
public Vector2 IconSize
{
@ -20,7 +22,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
private readonly Container iconContainer;
public IconPill(IconUsage icon)
protected IconPill(IconUsage icon)
{
AutoSizeAxes = Axes.Both;
Masking = true;
@ -47,5 +49,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
},
};
}
public abstract LocalisableString TooltipText { get; }
}
}

View File

@ -0,0 +1,19 @@
// 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.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Beatmaps.Drawables.Cards
{
public class StoryboardIconPill : IconPill
{
public StoryboardIconPill()
: base(FontAwesome.Solid.Image)
{
}
public override LocalisableString TooltipText => BeatmapsetsStrings.ShowInfoStoryboard;
}
}

View File

@ -0,0 +1,19 @@
// 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.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Beatmaps.Drawables.Cards
{
public class VideoIconPill : IconPill
{
public VideoIconPill()
: base(FontAwesome.Solid.Film)
{
}
public override LocalisableString TooltipText => BeatmapsetsStrings.ShowInfoVideo;
}
}

View File

@ -21,7 +21,7 @@ namespace osu.Game.Graphics.UserInterface
{
Size = TwoLayerButton.SIZE_EXTENDED;
Child = button = new TwoLayerButton(HoverSampleSet.Submit)
Child = button = new TwoLayerButton
{
Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft,

View File

@ -56,8 +56,8 @@ namespace osu.Game.Graphics.UserInterface
private readonly SpriteText spriteText;
private Vector2 hoverSpacing => new Vector2(3f, 0f);
public DialogButton()
: base(HoverSampleSet.Submit)
public DialogButton(HoverSampleSet sampleSet = HoverSampleSet.Button)
: base(sampleSet)
{
RelativeSizeAxes = Axes.X;

View File

@ -36,7 +36,7 @@ namespace osu.Game.Graphics.UserInterface
Icon = FontAwesome.Solid.ExternalLinkAlt,
RelativeSizeAxes = Axes.Both
},
new HoverClickSounds(HoverSampleSet.Submit)
new HoverClickSounds()
};
}

View File

@ -7,6 +7,7 @@ using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Extensions;
using osu.Framework.Input.Events;
using osu.Framework.Utils;
using osuTK.Input;
namespace osu.Game.Graphics.UserInterface
@ -37,7 +38,10 @@ namespace osu.Game.Graphics.UserInterface
protected override bool OnClick(ClickEvent e)
{
if (buttons.Contains(e.Button) && Contains(e.ScreenSpaceMousePosition))
sampleClick?.Play();
{
sampleClick.Frequency.Value = 0.99 + RNG.NextDouble(0.02);
sampleClick.Play();
}
return base.OnClick(e);
}

View File

@ -10,9 +10,6 @@ namespace osu.Game.Graphics.UserInterface
[Description("default")]
Default,
[Description("submit")]
Submit,
[Description("button")]
Button,

View File

@ -13,6 +13,7 @@ namespace osu.Game.Graphics.UserInterface
{
public class ShearedToggleButton : ShearedButton
{
private Sample? sampleClick;
private Sample? sampleOff;
private Sample? sampleOn;
@ -39,8 +40,9 @@ namespace osu.Game.Graphics.UserInterface
[BackgroundDependencyLoader]
private void load(AudioManager audio)
{
sampleOn = audio.Samples.Get(@"UI/check-on");
sampleOff = audio.Samples.Get(@"UI/check-off");
sampleClick = audio.Samples.Get(@"UI/default-select");
sampleOn = audio.Samples.Get(@"UI/dropdown-open");
sampleOff = audio.Samples.Get(@"UI/dropdown-close");
}
protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds(sampleSet);
@ -67,6 +69,8 @@ namespace osu.Game.Graphics.UserInterface
private void playSample()
{
sampleClick?.Play();
if (Active.Value)
sampleOn?.Play();
else

View File

@ -2,11 +2,13 @@
// See the LICENCE file in the repository root for full licence text.
using System.IO;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
@ -65,6 +67,9 @@ namespace osu.Game.Graphics.UserInterfaceV2
{
get
{
if (BeatmapModelManager.VIDEO_EXTENSIONS.Contains(File.Extension))
return FontAwesome.Regular.FileVideo;
switch (File.Extension)
{
case @".ogg":
@ -77,12 +82,6 @@ namespace osu.Game.Graphics.UserInterfaceV2
case @".png":
return FontAwesome.Regular.FileImage;
case @".mp4":
case @".avi":
case @".mov":
case @".flv":
return FontAwesome.Regular.FileVideo;
default:
return FontAwesome.Regular.File;
}

View File

@ -29,6 +29,11 @@ namespace osu.Game.Localisation
/// </summary>
public static LocalisableString DeleteAllBeatmaps => new TranslatableString(getKey(@"delete_all_beatmaps"), @"Delete ALL beatmaps");
/// <summary>
/// "Delete ALL beatmap videos"
/// </summary>
public static LocalisableString DeleteAllBeatmapVideos => new TranslatableString(getKey(@"delete_all_beatmap_videos"), @"Delete ALL beatmap videos");
/// <summary>
/// "Import scores from stable"
/// </summary>

View File

@ -38,7 +38,6 @@ namespace osu.Game.Online.Chat
}
public DrawableLinkCompiler(IEnumerable<Drawable> parts)
: base(HoverSampleSet.Submit)
{
Parts = parts.ToList();
}

View File

@ -155,9 +155,6 @@ namespace osu.Game.Online.Chat
{
public Func<Message, ChatLine> CreateChatLineAction;
[Resolved]
private OsuColour colours { get; set; }
public StandAloneDrawableChannel(Channel channel)
: base(channel)
{
@ -166,25 +163,40 @@ namespace osu.Game.Online.Chat
[BackgroundDependencyLoader]
private void load()
{
// TODO: Remove once DrawableChannel & ChatLine padding is fixed
ChatLineFlow.Padding = new MarginPadding { Horizontal = 0 };
}
protected override ChatLine CreateChatLine(Message m) => CreateChatLineAction(m);
protected override Drawable CreateDaySeparator(DateTimeOffset time) => new DaySeparator(time)
protected override DaySeparator CreateDaySeparator(DateTimeOffset time) => new StandAloneDaySeparator(time);
}
protected class StandAloneDaySeparator : DaySeparator
{
protected override float TextSize => 14;
protected override float LineHeight => 1;
protected override float Spacing => 10;
protected override float DateAlign => 120;
public StandAloneDaySeparator(DateTimeOffset time)
: base(time)
{
TextSize = 14,
Colour = colours.Yellow,
LineHeight = 1,
Padding = new MarginPadding { Horizontal = 10 },
Margin = new MarginPadding { Vertical = 5 },
};
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
Height = 25;
Colour = colours.Yellow;
// TODO: Remove once DrawableChannel & ChatLine padding is fixed
Padding = new MarginPadding { Horizontal = 10 };
}
}
protected class StandAloneMessage : ChatLine
{
protected override float TextSize => 15;
protected override float HorizontalPadding => 10;
protected override float MessagePadding => 120;
protected override float TimestampPadding => 50;

View File

@ -197,6 +197,7 @@ namespace osu.Game.Online.Multiplayer
APIRoom.Playlist.Clear();
APIRoom.Playlist.AddRange(joinedRoom.Playlist.Select(createPlaylistItem));
APIRoom.CurrentPlaylistItem.Value = APIRoom.Playlist.Single(item => item.ID == joinedRoom.Settings.PlaylistItemId);
Debug.Assert(LocalUser != null);
addUserToAPIRoom(LocalUser);
@ -737,6 +738,7 @@ namespace osu.Game.Online.Multiplayer
APIRoom.Type.Value = Room.Settings.MatchType;
APIRoom.QueueMode.Value = Room.Settings.QueueMode;
APIRoom.AutoStartDuration.Value = Room.Settings.AutoStartDuration;
APIRoom.CurrentPlaylistItem.Value = APIRoom.Playlist.Single(item => item.ID == settings.PlaylistItemId);
RoomUpdated?.Invoke();
}

View File

@ -61,7 +61,13 @@ namespace osu.Game.Online.Rooms
/// Used for serialising to the API.
/// </summary>
[JsonProperty("beatmap_id")]
private int onlineBeatmapId => Beatmap.OnlineID;
private int onlineBeatmapId
{
get => Beatmap.OnlineID;
// This setter is only required for client-side serialise-then-deserialise operations.
// Serialisation is supposed to emit only a `beatmap_id`, but a (non-null) `beatmap` is required on deserialise.
set => Beatmap = new APIBeatmap { OnlineID = value };
}
/// <summary>
/// A beatmap representing this playlist item.

View File

@ -162,6 +162,13 @@ namespace osu.Game.Online.Rooms
Password.BindValueChanged(p => HasPassword.Value = !string.IsNullOrEmpty(p.NewValue));
}
/// <summary>
/// Copies values from another <see cref="Room"/> into this one.
/// </summary>
/// <remarks>
/// **Beware**: This will store references between <see cref="Room"/>s.
/// </remarks>
/// <param name="other">The <see cref="Room"/> to copy values from.</param>
public void CopyFrom(Room other)
{
RoomID.Value = other.RoomID.Value;

View File

@ -5,6 +5,7 @@ using System;
using System.Linq;
using System.Threading.Tasks;
using osu.Framework.Allocation;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Utils;
@ -69,7 +70,7 @@ namespace osu.Game.Overlays.AccountCreation
},
usernameTextBox = new OsuTextBox
{
PlaceholderText = UsersStrings.LoginUsername,
PlaceholderText = UsersStrings.LoginUsername.ToLower(),
RelativeSizeAxes = Axes.X,
TabbableContentContainer = this
},
@ -91,7 +92,7 @@ namespace osu.Game.Overlays.AccountCreation
},
passwordTextBox = new OsuPasswordTextBox
{
PlaceholderText = "password",
PlaceholderText = UsersStrings.LoginPassword.ToLower(),
RelativeSizeAxes = Axes.X,
TabbableContentContainer = this,
},

View File

@ -40,7 +40,7 @@ namespace osu.Game.Overlays.BeatmapListing
Font = OsuFont.GetFont(size: 13, weight: FontWeight.Regular),
Text = LabelFor(Value)
},
new HoverClickSounds()
new HoverClickSounds(HoverSampleSet.TabSelect)
});
Enabled.Value = true;

View File

@ -6,10 +6,6 @@
using System;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.Chat;
namespace osu.Game.Overlays.Chat
@ -24,85 +20,19 @@ namespace osu.Game.Overlays.Chat
[BackgroundDependencyLoader]
private void load()
{
// TODO: Remove once DrawableChannel & ChatLine padding is fixed
ChatLineFlow.Padding = new MarginPadding(0);
}
protected override Drawable CreateDaySeparator(DateTimeOffset time) => new ChatOverlayDaySeparator(time);
protected override DaySeparator CreateDaySeparator(DateTimeOffset time) => new ChatOverlayDaySeparator(time);
private class ChatOverlayDaySeparator : Container
private class ChatOverlayDaySeparator : DaySeparator
{
private readonly DateTimeOffset time;
public ChatOverlayDaySeparator(DateTimeOffset time)
: base(time)
{
this.time = time;
}
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider)
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
Padding = new MarginPadding { Horizontal = 15, Vertical = 20 };
Child = new GridContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
ColumnDimensions = new[]
{
new Dimension(GridSizeMode.Absolute, 200),
new Dimension(GridSizeMode.Absolute, 15),
new Dimension(),
},
Content = new[]
{
new[]
{
new GridContainer
{
RelativeSizeAxes = Axes.Both,
ColumnDimensions = new[]
{
new Dimension(),
new Dimension(GridSizeMode.Absolute, 15),
new Dimension(GridSizeMode.AutoSize),
},
Content = new[]
{
new[]
{
new Circle
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Colour = colourProvider.Background5,
RelativeSizeAxes = Axes.X,
Height = 2,
},
Drawable.Empty(),
new OsuSpriteText
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Text = time.ToLocalTime().ToString("dd MMMM yyyy").ToUpper(),
Font = OsuFont.Torus.With(size: 15, weight: FontWeight.SemiBold),
Colour = colourProvider.Content1,
},
},
},
},
Drawable.Empty(),
new Circle
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Colour = colourProvider.Background5,
RelativeSizeAxes = Axes.X,
Height = 2,
},
},
},
};
// TODO: Remove once DrawableChannel & ChatLine padding is fixed
Padding = new MarginPadding { Horizontal = 15 };
}
}
}

View File

@ -0,0 +1,105 @@
// 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 System;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
namespace osu.Game.Overlays.Chat
{
public class DaySeparator : Container
{
protected virtual float TextSize => 15;
protected virtual float LineHeight => 2;
protected virtual float DateAlign => 200;
protected virtual float Spacing => 15;
private readonly DateTimeOffset time;
[Resolved(CanBeNull = true)]
private OverlayColourProvider? colourProvider { get; set; }
public DaySeparator(DateTimeOffset time)
{
this.time = time;
Height = 40;
}
[BackgroundDependencyLoader]
private void load()
{
RelativeSizeAxes = Axes.X;
Child = new GridContainer
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
RowDimensions = new[] { new Dimension() },
ColumnDimensions = new[]
{
new Dimension(GridSizeMode.Absolute, DateAlign),
new Dimension(GridSizeMode.Absolute, Spacing),
new Dimension(),
},
Content = new[]
{
new[]
{
new GridContainer
{
RelativeSizeAxes = Axes.Both,
RowDimensions = new[] { new Dimension() },
ColumnDimensions = new[]
{
new Dimension(),
new Dimension(GridSizeMode.Absolute, Spacing),
new Dimension(GridSizeMode.AutoSize),
},
Content = new[]
{
new[]
{
new Circle
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Height = LineHeight,
Colour = colourProvider?.Background5 ?? Colour4.White,
},
Drawable.Empty(),
new OsuSpriteText
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Text = time.ToLocalTime().ToString("dd MMMM yyyy").ToUpper(),
Font = OsuFont.Torus.With(size: TextSize, weight: FontWeight.SemiBold),
Colour = colourProvider?.Content1 ?? Colour4.White,
},
}
},
},
Drawable.Empty(),
new Circle
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Height = LineHeight,
Colour = colourProvider?.Background5 ?? Colour4.White,
},
}
}
};
}
}
}

View File

@ -7,14 +7,9 @@ using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Graphics.Cursor;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.Chat;
using osuTK.Graphics;
@ -40,9 +35,6 @@ namespace osu.Game.Overlays.Chat
}
}
[Resolved]
private OsuColour colours { get; set; }
public DrawableChannel(Channel channel)
{
Channel = channel;
@ -67,7 +59,7 @@ namespace osu.Game.Overlays.Chat
Padding = new MarginPadding { Bottom = 5 },
Child = ChatLineFlow = new FillFlowContainer
{
Padding = new MarginPadding { Left = 20, Right = 20 },
Padding = new MarginPadding { Horizontal = 15 },
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
@ -121,11 +113,7 @@ namespace osu.Game.Overlays.Chat
protected virtual ChatLine CreateChatLine(Message m) => new ChatLine(m);
protected virtual Drawable CreateDaySeparator(DateTimeOffset time) => new DaySeparator(time)
{
Colour = colours.ChatBlue.Lighten(0.7f),
Margin = new MarginPadding { Vertical = 10 },
};
protected virtual DaySeparator CreateDaySeparator(DateTimeOffset time) => new DaySeparator(time);
private void newMessagesArrived(IEnumerable<Message> newMessages) => Schedule(() =>
{
@ -203,69 +191,5 @@ namespace osu.Game.Overlays.Chat
});
private IEnumerable<ChatLine> chatLines => ChatLineFlow.Children.OfType<ChatLine>();
public class DaySeparator : Container
{
public float TextSize
{
get => text.Font.Size;
set => text.Font = text.Font.With(size: value);
}
private float lineHeight = 2;
public float LineHeight
{
get => lineHeight;
set => lineHeight = leftBox.Height = rightBox.Height = value;
}
private readonly SpriteText text;
private readonly Box leftBox;
private readonly Box rightBox;
public DaySeparator(DateTimeOffset time)
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
Child = new GridContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
ColumnDimensions = new[]
{
new Dimension(),
new Dimension(GridSizeMode.AutoSize),
new Dimension(),
},
RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize), },
Content = new[]
{
new Drawable[]
{
leftBox = new Box
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Height = lineHeight,
},
text = new OsuSpriteText
{
Margin = new MarginPadding { Horizontal = 10 },
Text = time.ToLocalTime().ToString("dd MMM yyyy"),
},
rightBox = new Box
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Height = lineHeight,
},
}
}
};
}
}
}
}

View File

@ -6,6 +6,8 @@
using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@ -16,6 +18,7 @@ using osu.Framework.Localisation;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.Chat;
using osuTK;
@ -32,6 +35,8 @@ namespace osu.Game.Overlays.Chat.Listing
public IEnumerable<LocalisableString> FilterTerms => new LocalisableString[] { Channel.Name, Channel.Topic ?? string.Empty };
public bool MatchingFilter { set => this.FadeTo(value ? 1f : 0f, 100); }
protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds();
private Box hoverBox = null!;
private SpriteIcon checkbox = null!;
private OsuSpriteText channelText = null!;
@ -46,14 +51,20 @@ namespace osu.Game.Overlays.Chat.Listing
private const float vertical_margin = 1.5f;
private Sample? sampleJoin;
private Sample? sampleLeave;
public ChannelListingItem(Channel channel)
{
Channel = channel;
}
[BackgroundDependencyLoader]
private void load()
private void load(AudioManager audio)
{
sampleJoin = audio.Samples.Get(@"UI/check-on");
sampleLeave = audio.Samples.Get(@"UI/check-off");
Masking = true;
CornerRadius = 5;
RelativeSizeAxes = Axes.X;
@ -156,7 +167,19 @@ namespace osu.Game.Overlays.Chat.Listing
}
}, true);
Action = () => (channelJoined.Value ? OnRequestLeave : OnRequestJoin)?.Invoke(Channel);
Action = () =>
{
if (channelJoined.Value)
{
OnRequestLeave?.Invoke(Channel);
sampleLeave?.Play();
}
else
{
OnRequestJoin?.Invoke(Channel);
sampleJoin?.Play();
}
};
}
protected override bool OnHover(HoverEvent e)

View File

@ -14,7 +14,6 @@ using osu.Framework.Platform;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.News
@ -29,7 +28,6 @@ namespace osu.Game.Overlays.News
private TextFlowContainer main;
public NewsCard(APINewsPost post)
: base(HoverSampleSet.Submit)
{
this.post = post;

View File

@ -18,7 +18,6 @@ using System.Diagnostics;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Platform;
using osu.Game.Graphics.UserInterface;
namespace osu.Game.Overlays.News.Sidebar
{
@ -129,7 +128,6 @@ namespace osu.Game.Overlays.News.Sidebar
private readonly APINewsPost post;
public PostButton(APINewsPost post)
: base(HoverSampleSet.Submit)
{
this.post = post;

View File

@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Profile.Header.Components
private Sample sampleOpen;
private Sample sampleClose;
protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds();
protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverClickSounds();
public ExpandDetailsButton()
{

View File

@ -6,7 +6,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
namespace osu.Game.Overlays.Profile.Sections
{
@ -18,7 +17,6 @@ namespace osu.Game.Overlays.Profile.Sections
private readonly IBeatmapInfo beatmapInfo;
protected BeatmapMetadataContainer(IBeatmapInfo beatmapInfo)
: base(HoverSampleSet.Submit)
{
this.beatmapInfo = beatmapInfo;

View File

@ -28,6 +28,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
private SettingsButton deleteSkinsButton;
private SettingsButton restoreButton;
private SettingsButton undeleteButton;
private SettingsButton deleteBeatmapVideosButton;
[BackgroundDependencyLoader(permitNulls: true)]
private void load(BeatmapManager beatmaps, ScoreManager scores, SkinManager skins, [CanBeNull] CollectionManager collectionManager, [CanBeNull] LegacyImportManager legacyImportManager, IDialogOverlay dialogOverlay)
@ -58,6 +59,19 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
}
});
Add(deleteBeatmapVideosButton = new DangerousSettingsButton
{
Text = MaintenanceSettingsStrings.DeleteAllBeatmapVideos,
Action = () =>
{
dialogOverlay?.Push(new MassVideoDeleteConfirmationDialog(() =>
{
deleteBeatmapVideosButton.Enabled.Value = false;
Task.Run(beatmaps.DeleteAllVideos).ContinueWith(t => Schedule(() => deleteBeatmapVideosButton.Enabled.Value = true));
}));
}
});
if (legacyImportManager?.SupportsImportFromStable == true)
{
Add(importScoresButton = new SettingsButton

View File

@ -0,0 +1,16 @@
// 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 System;
namespace osu.Game.Overlays.Settings.Sections.Maintenance
{
public class MassVideoDeleteConfirmationDialog : MassDeleteConfirmationDialog
{
public MassVideoDeleteConfirmationDialog(Action deleteAction)
: base(deleteAction)
{
BodyText = "All beatmap videos? This cannot be undone!";
}
}
}

View File

@ -20,7 +20,6 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Input.Bindings;
using osuTK;
using osuTK.Graphics;
@ -83,7 +82,6 @@ namespace osu.Game.Overlays.Toolbar
private RealmAccess realm { get; set; }
protected ToolbarButton()
: base(HoverSampleSet.Toolbar)
{
Width = Toolbar.HEIGHT;
RelativeSizeAxes = Axes.Y;

View File

@ -11,7 +11,6 @@ using osu.Framework.Input.Events;
using osu.Game.Configuration;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osuTK;
using osuTK.Graphics;
@ -29,7 +28,6 @@ namespace osu.Game.Overlays.Toolbar
private AnalogClockDisplay analog;
public ToolbarClock()
: base(HoverSampleSet.Toolbar)
{
RelativeSizeAxes = Axes.Y;
AutoSizeAxes = Axes.X;

View File

@ -460,6 +460,7 @@ namespace osu.Game.Rulesets.Scoring
currentMaximumScoringValues.BaseScore = maximum.BaseScore;
currentMaximumScoringValues.MaxCombo = maximum.MaxCombo;
Combo.Value = frame.Header.Combo;
HighestCombo.Value = frame.Header.MaxCombo;
scoreResultCounts.Clear();

View File

@ -7,6 +7,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Transforms;
using osu.Framework.Input.Events;
using osu.Framework.Layout;
using osu.Framework.Timing;
using osu.Framework.Utils;
using osu.Game.Graphics.Containers;
@ -40,10 +41,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
[Resolved(canBeNull: true)]
private IFrameBasedClock editorClock { get; set; }
private readonly LayoutValue zoomedContentWidthCache = new LayoutValue(Invalidation.DrawSize);
public ZoomableScrollContainer()
: base(Direction.Horizontal)
{
base.Content.Add(zoomedContent = new Container { RelativeSizeAxes = Axes.Y });
AddLayout(zoomedContentWidthCache);
}
private float minZoom = 1;
@ -103,12 +108,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
}
}
protected override void LoadComplete()
protected override void Update()
{
base.LoadComplete();
base.Update();
// This width only gets updated on the application of a transform, so this needs to be initialized here.
updateZoomedContentWidth();
if (!zoomedContentWidthCache.IsValid)
updateZoomedContentWidth();
}
protected override bool OnScroll(ScrollEvent e)
@ -128,7 +133,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
return base.OnScroll(e);
}
private void updateZoomedContentWidth() => zoomedContent.Width = DrawWidth * currentZoom;
private void updateZoomedContentWidth()
{
zoomedContent.Width = DrawWidth * currentZoom;
zoomedContentWidthCache.Validate();
}
private float zoomTarget = 1;
@ -199,8 +208,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
float targetOffset = expectedWidth * (focusPoint / contentSize) - focusOffset;
d.currentZoom = newZoom;
d.updateZoomedContentWidth();
// Temporarily here to make sure ScrollTo gets the correct DrawSize for scrollable area.
// TODO: Make sure draw size gets invalidated properly on the framework side, and remove this once it is.
d.Invalidate(Invalidation.DrawSize);

View File

@ -55,7 +55,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
private void load(AudioManager audio)
{
sampleSelect = audio.Samples.Get($@"UI/{HoverSampleSet.Default.GetDescription()}-select");
sampleJoin = audio.Samples.Get($@"UI/{HoverSampleSet.Submit.GetDescription()}-select");
sampleJoin = audio.Samples.Get($@"UI/{HoverSampleSet.Button.GetDescription()}-select");
AddRangeInternal(new Drawable[]
{

View File

@ -8,6 +8,7 @@ using System.Threading;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
@ -244,7 +245,7 @@ namespace osu.Game.Screens.Select.Carousel
}
if (hideRequested != null)
items.Add(new OsuMenuItem("Hide", MenuItemType.Destructive, () => hideRequested(beatmapInfo)));
items.Add(new OsuMenuItem(CommonStrings.ButtonsHide.ToSentence(), MenuItemType.Destructive, () => hideRequested(beatmapInfo)));
return items.ToArray();
}

View File

@ -15,7 +15,7 @@ namespace osu.Game.Screens.Select.Filter
[Description("Author")]
Author,
[LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatsBpm))]
[LocalisableDescription(typeof(SortStrings), nameof(SortStrings.ArtistTracksBpm))]
BPM,
[Description("Date Added")]
@ -28,10 +28,10 @@ namespace osu.Game.Screens.Select.Filter
Length,
// todo: pending support (https://github.com/ppy/osu/issues/4917)
// [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchFiltersRank))]
// [Description("Rank Achieved")]
// RankAchieved,
[LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowInfoSource))]
[Description("Source")]
Source,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingTitle))]

View File

@ -66,7 +66,7 @@ namespace osu.Game.Screens.Select
private readonly Box light;
public FooterButton()
: base(HoverSampleSet.Button)
: base(HoverSampleSet.Toolbar)
{
AutoSizeAxes = Axes.Both;
Shear = SHEAR;

View File

@ -77,7 +77,7 @@ namespace osu.Game.Screens.Select.Options
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => box.ReceivePositionalInputAt(screenSpacePos);
public BeatmapOptionsButton()
: base(HoverSampleSet.Submit)
: base(HoverSampleSet.Button)
{
Width = width;
RelativeSizeAxes = Axes.Y;

View File

@ -127,6 +127,9 @@ namespace osu.Game.Skinning.Editor
private void setTarget(OsuScreen target)
{
if (target == null)
return;
Debug.Assert(skinEditor != null);
if (!target.IsLoaded)

View File

@ -23,7 +23,7 @@ namespace osu.Game.Skinning
/// The <see cref="ISkin"/> which is being transformed.
/// </summary>
[NotNull]
protected internal ISkin Skin { get; }
public ISkin Skin { get; }
protected LegacySkinTransformer([NotNull] ISkin skin)
{

View File

@ -3,7 +3,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Newtonsoft.Json;
using osu.Game.Beatmaps;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
@ -44,9 +46,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay
switch (request)
{
case CreateRoomRequest createRoomRequest:
var apiRoom = new Room();
apiRoom.CopyFrom(createRoomRequest.Room);
var apiRoom = cloneRoom(createRoomRequest.Room);
// Passwords are explicitly not copied between rooms.
apiRoom.HasPassword.Value = !string.IsNullOrEmpty(createRoomRequest.Room.Password.Value);
@ -178,12 +178,31 @@ namespace osu.Game.Tests.Visual.OnlinePlay
private Room createResponseRoom(Room room, bool withParticipants)
{
var responseRoom = new Room();
responseRoom.CopyFrom(room);
var responseRoom = cloneRoom(room);
// Password is hidden from the response, and is only propagated via HasPassword.
bool hadPassword = responseRoom.HasPassword.Value;
responseRoom.Password.Value = null;
responseRoom.HasPassword.Value = hadPassword;
if (!withParticipants)
responseRoom.RecentParticipants.Clear();
return responseRoom;
}
private Room cloneRoom(Room source)
{
var result = JsonConvert.DeserializeObject<Room>(JsonConvert.SerializeObject(source));
Debug.Assert(result != null);
// Playlist item IDs aren't serialised.
if (source.CurrentPlaylistItem.Value != null)
result.CurrentPlaylistItem.Value.ID = source.CurrentPlaylistItem.Value.ID;
for (int i = 0; i < source.Playlist.Count; i++)
result.Playlist[i].ID = source.Playlist[i].ID;
return result;
}
}
}

View File

@ -7,7 +7,6 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events;
using osu.Framework.Localisation;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Users.Drawables
@ -74,11 +73,6 @@ namespace osu.Game.Users.Drawables
{
private LocalisableString tooltip = default_tooltip_text;
public ClickableArea()
: base(HoverSampleSet.Submit)
{
}
public override LocalisableString TooltipText
{
get => Enabled.Value ? tooltip : default;

View File

@ -49,7 +49,7 @@ namespace osu.Game.Users.Drawables
{
RelativeSizeAxes = Axes.Both
},
new HoverClickSounds(HoverSampleSet.Submit)
new HoverClickSounds()
}
};
}

View File

@ -32,7 +32,7 @@ namespace osu.Game.Users
protected Drawable Background { get; private set; }
protected UserPanel(APIUser user)
: base(HoverSampleSet.Submit)
: base(HoverSampleSet.Button)
{
if (user == null)
throw new ArgumentNullException(nameof(user));

View File

@ -36,7 +36,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Realm" Version="10.14.0" />
<PackageReference Include="ppy.osu.Framework" Version="2022.603.1" />
<PackageReference Include="ppy.osu.Framework" Version="2022.605.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.527.0" />
<PackageReference Include="Sentry" Version="3.17.1" />
<PackageReference Include="SharpCompress" Version="0.31.0" />

View File

@ -61,7 +61,7 @@
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Framework.iOS" Version="2022.603.1" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2022.605.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.527.0" />
</ItemGroup>
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net6.0) -->
@ -84,7 +84,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.14" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="5.0.14" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="ppy.osu.Framework" Version="2022.603.1" />
<PackageReference Include="ppy.osu.Framework" Version="2022.605.0" />
<PackageReference Include="SharpCompress" Version="0.31.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />