1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 08:43:01 +08:00

Merge branch 'master' into editor-select-timing-on-enter

This commit is contained in:
Bartłomiej Dach 2023-02-11 16:27:22 +01:00
commit 774eae98cc
No known key found for this signature in database
28 changed files with 199 additions and 127 deletions

View File

@ -17,7 +17,7 @@
<EmbeddedResource Include="Resources\**\*.*" />
</ItemGroup>
<ItemGroup Label="Code Analysis">
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3" PrivateAssets="All" />
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.4" PrivateAssets="All" />
<AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\BannedSymbols.txt" />
</ItemGroup>
<PropertyGroup Label="Code Analysis">

View File

@ -9,9 +9,9 @@
<GenerateProgramFile>false</GenerateProgramFile>
</PropertyGroup>
<ItemGroup Label="Package References">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\osu.Game.Rulesets.EmptyFreeform\osu.Game.Rulesets.EmptyFreeform.csproj" />

View File

@ -9,9 +9,9 @@
<GenerateProgramFile>false</GenerateProgramFile>
</PropertyGroup>
<ItemGroup Label="Package References">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj" />

View File

@ -9,9 +9,9 @@
<GenerateProgramFile>false</GenerateProgramFile>
</PropertyGroup>
<ItemGroup Label="Package References">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\osu.Game.Rulesets.EmptyScrolling\osu.Game.Rulesets.EmptyScrolling.csproj" />

View File

@ -9,9 +9,9 @@
<GenerateProgramFile>false</GenerateProgramFile>
</PropertyGroup>
<ItemGroup Label="Package References">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj" />

View File

@ -98,7 +98,7 @@ namespace osu.Desktop
if (status.Value is UserStatusOnline && activity.Value != null)
{
presence.State = truncate(activity.Value.Status);
presence.State = truncate(activity.Value.GetStatus(privacyMode.Value == DiscordRichPresenceMode.Limited));
presence.Details = truncate(getDetails(activity.Value));
if (getBeatmap(activity.Value) is IBeatmapInfo beatmap && beatmap.OnlineID > 0)
@ -186,6 +186,9 @@ namespace osu.Desktop
case UserActivity.Editing edit:
return edit.BeatmapInfo.ToString() ?? string.Empty;
case UserActivity.Watching watching:
return watching.BeatmapInfo.ToString();
case UserActivity.InLobby lobby:
return privacyMode.Value == DiscordRichPresenceMode.Limited ? string.Empty : lobby.Room.Name.Value;
}

View File

@ -26,8 +26,8 @@
<ItemGroup Label="Package References">
<PackageReference Include="Clowd.Squirrel" Version="2.9.42" />
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
<PackageReference Include="System.IO.Packaging" Version="6.0.0" />
<PackageReference Include="DiscordRichPresence" Version="1.1.1.14" />
<PackageReference Include="System.IO.Packaging" Version="7.0.0" />
<PackageReference Include="DiscordRichPresence" Version="1.1.3.18" />
</ItemGroup>
<ItemGroup Label="Resources">
<EmbeddedResource Include="lazer.ico" />

View File

@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
<PackageReference Include="BenchmarkDotNet" Version="0.13.4" />
<PackageReference Include="nunit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
</ItemGroup>
<ItemGroup>

View File

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
</ItemGroup>
<PropertyGroup Label="Project">
<OutputType>WinExe</OutputType>

View File

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
</ItemGroup>
<PropertyGroup Label="Project">
<OutputType>WinExe</OutputType>

View File

@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Moq" Version="4.18.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
</ItemGroup>
<PropertyGroup Label="Project">
<OutputType>WinExe</OutputType>

View File

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
</ItemGroup>
<PropertyGroup Label="Project">
<OutputType>WinExe</OutputType>

View File

@ -1,32 +1,64 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Linq;
using NUnit.Framework;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Play;
using osu.Game.Tests.Beatmaps;
using osuTK.Input;
namespace osu.Game.Tests.Visual.Gameplay
{
public partial class TestSceneReplayPlayer : RateAdjustedBeatmapTestScene
{
protected TestReplayPlayer Player;
public override void SetUpSteps()
{
base.SetUpSteps();
AddStep("Initialise player", () => Player = CreatePlayer(new OsuRuleset()));
AddStep("Load player", () => LoadScreen(Player));
AddUntilStep("player loaded", () => Player.IsLoaded);
}
protected TestReplayPlayer Player = null!;
[Test]
public void TestPauseViaSpace()
{
loadPlayerWithBeatmap();
double? lastTime = null;
AddUntilStep("wait for first hit", () => Player.ScoreProcessor.TotalScore.Value > 0);
AddStep("Pause playback with space", () => InputManager.Key(Key.Space));
AddAssert("player not exited", () => Player.IsCurrentScreen());
AddUntilStep("Time stopped progressing", () =>
{
double current = Player.GameplayClockContainer.CurrentTime;
bool changed = lastTime != current;
lastTime = current;
return !changed;
});
AddWaitStep("wait some", 10);
AddAssert("Time still stopped", () => lastTime == Player.GameplayClockContainer.CurrentTime);
}
[Test]
public void TestPauseViaSpaceWithSkip()
{
loadPlayerWithBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo)
{
BeatmapInfo = { AudioLeadIn = 60000 }
});
AddUntilStep("wait for skip overlay", () => Player.ChildrenOfType<SkipOverlay>().First().IsButtonVisible);
AddStep("Skip with space", () => InputManager.Key(Key.Space));
AddAssert("Player not paused", () => !Player.DrawableRuleset.IsPaused.Value);
double? lastTime = null;
AddUntilStep("wait for first hit", () => Player.ScoreProcessor.TotalScore.Value > 0);
@ -52,6 +84,8 @@ namespace osu.Game.Tests.Visual.Gameplay
[Test]
public void TestPauseViaMiddleMouse()
{
loadPlayerWithBeatmap();
double? lastTime = null;
AddUntilStep("wait for first hit", () => Player.ScoreProcessor.TotalScore.Value > 0);
@ -77,6 +111,8 @@ namespace osu.Game.Tests.Visual.Gameplay
[Test]
public void TestSeekBackwards()
{
loadPlayerWithBeatmap();
double? lastTime = null;
AddUntilStep("wait for first hit", () => Player.ScoreProcessor.TotalScore.Value > 0);
@ -93,6 +129,8 @@ namespace osu.Game.Tests.Visual.Gameplay
[Test]
public void TestSeekForwards()
{
loadPlayerWithBeatmap();
double? lastTime = null;
AddUntilStep("wait for first hit", () => Player.ScoreProcessor.TotalScore.Value > 0);
@ -106,12 +144,26 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("Jumped forwards", () => Player.GameplayClockContainer.CurrentTime - lastTime > 500);
}
protected TestReplayPlayer CreatePlayer(Ruleset ruleset)
private void loadPlayerWithBeatmap(IBeatmap? beatmap = null)
{
Beatmap.Value = CreateWorkingBeatmap(ruleset.RulesetInfo);
AddStep("create player", () =>
{
CreatePlayer(new OsuRuleset(), beatmap);
});
AddStep("Load player", () => LoadScreen(Player));
AddUntilStep("player loaded", () => Player.IsLoaded);
}
protected void CreatePlayer(Ruleset ruleset, IBeatmap? beatmap = null)
{
Beatmap.Value = beatmap != null
? CreateWorkingBeatmap(beatmap)
: CreateWorkingBeatmap(ruleset.RulesetInfo);
SelectedMods.Value = new[] { ruleset.GetAutoplayMod() };
return new TestReplayPlayer(false);
Player = new TestReplayPlayer(false);
}
}
}

View File

@ -11,6 +11,8 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets;
using osu.Game.Scoring;
using osu.Game.Tests.Beatmaps;
using osu.Game.Users;
using osuTK;
@ -107,7 +109,8 @@ namespace osu.Game.Tests.Visual.Online
AddStep("set online status", () => status.Value = new UserStatusOnline());
AddStep("idle", () => activity.Value = null);
AddStep("spectating", () => activity.Value = new UserActivity.Spectating());
AddStep("watching", () => activity.Value = new UserActivity.Watching(createScore(@"nats")));
AddStep("spectating", () => activity.Value = new UserActivity.Spectating(createScore(@"mrekk")));
AddStep("solo (osu!)", () => activity.Value = soloGameStatusForRuleset(0));
AddStep("solo (osu!taiko)", () => activity.Value = soloGameStatusForRuleset(1));
AddStep("solo (osu!catch)", () => activity.Value = soloGameStatusForRuleset(2));
@ -132,6 +135,14 @@ namespace osu.Game.Tests.Visual.Online
private UserActivity soloGameStatusForRuleset(int rulesetId) => new UserActivity.InSoloGame(null, rulesetStore.GetRuleset(rulesetId));
private ScoreInfo createScore(string name) => new ScoreInfo(new TestBeatmap(Ruleset.Value).BeatmapInfo)
{
User = new APIUser
{
Username = name,
}
};
private partial class TestUserListPanel : UserListPanel
{
public TestUserListPanel(APIUser user)

View File

@ -2,11 +2,11 @@
<Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References">
<PackageReference Include="DeepEqual" Version="4.2.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
<PackageReference Include="Moq" Version="4.18.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
<PackageReference Include="Moq" Version="4.18.4" />
</ItemGroup>
<PropertyGroup Label="Project">
<OutputType>WinExe</OutputType>

View File

@ -4,9 +4,9 @@
<StartupObject>osu.Game.Tournament.Tests.TournamentTestRunner</StartupObject>
</PropertyGroup>
<ItemGroup Label="Package References">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
</ItemGroup>
<PropertyGroup Label="Project">
<OutputType>WinExe</OutputType>

View File

@ -35,8 +35,8 @@ namespace osu.Game.Input.Bindings
// It is used to decide the order of precedence, with the earlier items having higher precedence.
public override IEnumerable<IKeyBinding> DefaultKeyBindings => GlobalKeyBindings
.Concat(EditorKeyBindings)
.Concat(ReplayKeyBindings)
.Concat(InGameKeyBindings)
.Concat(ReplayKeyBindings)
.Concat(SongSelectKeyBindings)
.Concat(AudioControlKeyBindings)
// Overlay bindings may conflict with more local cases like the editor so they are checked last.

View File

@ -95,7 +95,7 @@ namespace osu.Game.Online.Chat
{
connector.ChannelJoined += ch => Schedule(() => joinChannel(ch));
connector.ChannelParted += ch => Schedule(() => LeaveChannel(getChannel(ch)));
connector.ChannelParted += ch => Schedule(() => leaveChannel(getChannel(ch), false));
connector.NewMessages += msgs => Schedule(() => addMessages(msgs));
@ -558,7 +558,9 @@ namespace osu.Game.Online.Chat
/// Leave the specified channel. Can be called from any thread.
/// </summary>
/// <param name="channel">The channel to leave.</param>
public void LeaveChannel(Channel channel) => Schedule(() =>
public void LeaveChannel(Channel channel) => Schedule(() => leaveChannel(channel, true));
private void leaveChannel(Channel channel, bool sendLeaveRequest)
{
if (channel == null) return;
@ -581,10 +583,11 @@ namespace osu.Game.Online.Chat
if (channel.Joined.Value)
{
api.Queue(new LeaveChannelRequest(channel));
if (sendLeaveRequest)
api.Queue(new LeaveChannelRequest(channel));
channel.Joined.Value = false;
}
});
}
/// <summary>
/// Opens the most recently closed channel that has not already been reopened,

View File

@ -148,9 +148,9 @@ namespace osu.Game.Overlays.SkinEditor
component.Origin = Anchor.Centre;
}
protected override void Update()
protected override void UpdateAfterChildren()
{
base.Update();
base.UpdateAfterChildren();
if (component.DrawSize != Vector2.Zero)
{

View File

@ -121,8 +121,8 @@ namespace osu.Game.Screens.Play.HUD
AutoSizeAxes = Axes.Both,
Child = new UprightAspectMaintainingContainer
{
Origin = Anchor.CentreRight,
Anchor = Anchor.CentreRight,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
AutoSizeAxes = Axes.Both,
Scaling = ScaleMode.Vertical,
ScalingFactor = 0.5f,

View File

@ -15,6 +15,7 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Scoring;
using osu.Game.Screens.Play.HUD;
using osu.Game.Screens.Ranking;
using osu.Game.Users;
namespace osu.Game.Screens.Play
{
@ -24,6 +25,8 @@ namespace osu.Game.Screens.Play
private readonly bool replayIsFailedScore;
protected override UserActivity InitialActivity => new UserActivity.Watching(Score.ScoreInfo);
// Disallow replays from failing. (see https://github.com/ppy/osu/issues/6108)
protected override bool CheckModsAllowFailure()
{

View File

@ -7,6 +7,7 @@ using osu.Framework.Allocation;
using osu.Framework.Screens;
using osu.Game.Online.Spectator;
using osu.Game.Scoring;
using osu.Game.Users;
namespace osu.Game.Screens.Play
{
@ -14,6 +15,8 @@ namespace osu.Game.Screens.Play
{
private readonly Score score;
protected override UserActivity InitialActivity => new UserActivity.Spectating(Score.ScoreInfo);
public SoloSpectatorPlayer(Score score, PlayerConfiguration configuration = null)
: base(score, configuration)
{

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
namespace osu.Game.Tests.Visual
{
/// <summary>

View File

@ -1,11 +1,8 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events;
using osu.Framework.Localisation;
using osu.Game.Graphics.Containers;
@ -13,56 +10,49 @@ using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Users.Drawables
{
public partial class ClickableAvatar : Container
public partial class ClickableAvatar : OsuClickableContainer
{
private const string default_tooltip_text = "view profile";
/// <summary>
/// Whether to open the user's profile when clicked.
/// </summary>
public bool OpenOnClick
public override LocalisableString TooltipText
{
set => clickableArea.Enabled.Value = clickableArea.Action != null && value;
get
{
if (!Enabled.Value)
return string.Empty;
return ShowUsernameTooltip ? (user?.Username ?? string.Empty) : default_tooltip_text;
}
set => throw new NotSupportedException();
}
/// <summary>
/// By default, the tooltip will show "view profile" as avatars are usually displayed next to a username.
/// Setting this to <c>true</c> exposes the username via tooltip for special cases where this is not true.
/// </summary>
public bool ShowUsernameTooltip
{
set => clickableArea.TooltipText = value ? (user?.Username ?? string.Empty) : default_tooltip_text;
}
public bool ShowUsernameTooltip { get; set; }
private readonly APIUser user;
private readonly APIUser? user;
[Resolved(CanBeNull = true)]
private OsuGame game { get; set; }
private readonly ClickableArea clickableArea;
[Resolved]
private OsuGame? game { get; set; }
/// <summary>
/// A clickable avatar for the specified user, with UI sounds included.
/// If <see cref="OpenOnClick"/> is <c>true</c>, clicking will open the user's profile.
/// </summary>
/// <param name="user">The user. A null value will get a placeholder avatar.</param>
public ClickableAvatar(APIUser user = null)
public ClickableAvatar(APIUser? user = null)
{
this.user = user;
Add(clickableArea = new ClickableArea
{
RelativeSizeAxes = Axes.Both,
});
if (user?.Id != APIUser.SYSTEM_USER_ID)
clickableArea.Action = openProfile;
Action = openProfile;
}
[BackgroundDependencyLoader]
private void load()
{
LoadComponentAsync(new DrawableAvatar(user), clickableArea.Add);
LoadComponentAsync(new DrawableAvatar(user), Add);
}
private void openProfile()
@ -71,23 +61,12 @@ namespace osu.Game.Users.Drawables
game?.ShowUser(user);
}
private partial class ClickableArea : OsuClickableContainer
protected override bool OnClick(ClickEvent e)
{
private LocalisableString tooltip = default_tooltip_text;
if (!Enabled.Value)
return false;
public override LocalisableString TooltipText
{
get => Enabled.Value ? tooltip : default;
set => tooltip = value;
}
protected override bool OnClick(ClickEvent e)
{
if (!Enabled.Value)
return false;
return base.OnClick(e);
}
return base.OnClick(e);
}
}
}

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
@ -13,9 +11,9 @@ namespace osu.Game.Users.Drawables
/// <summary>
/// An avatar which can update to a new user when needed.
/// </summary>
public partial class UpdateableAvatar : ModelBackedDrawable<APIUser>
public partial class UpdateableAvatar : ModelBackedDrawable<APIUser?>
{
public APIUser User
public APIUser? User
{
get => Model;
set => Model = value;
@ -58,7 +56,7 @@ namespace osu.Game.Users.Drawables
/// <param name="isInteractive">If set to true, hover/click sounds will play and clicking the avatar will open the user's profile.</param>
/// <param name="showUsernameTooltip">Whether to show the username rather than "view profile" on the tooltip. (note: this only applies if <paramref name="isInteractive"/> is also true)</param>
/// <param name="showGuestOnNull">Whether to show a default guest representation on null user (as opposed to nothing).</param>
public UpdateableAvatar(APIUser user = null, bool isInteractive = true, bool showUsernameTooltip = false, bool showGuestOnNull = true)
public UpdateableAvatar(APIUser? user = null, bool isInteractive = true, bool showUsernameTooltip = false, bool showGuestOnNull = true)
{
this.isInteractive = isInteractive;
this.showUsernameTooltip = showUsernameTooltip;
@ -67,7 +65,7 @@ namespace osu.Game.Users.Drawables
User = user;
}
protected override Drawable CreateDrawable(APIUser user)
protected override Drawable? CreateDrawable(APIUser? user)
{
if (user == null && !showGuestOnNull)
return null;
@ -76,7 +74,6 @@ namespace osu.Game.Users.Drawables
{
return new ClickableAvatar(user)
{
OpenOnClick = true,
ShowUsernameTooltip = showUsernameTooltip,
RelativeSizeAxes = Axes.Both,
};

View File

@ -106,7 +106,7 @@ namespace osu.Game.Users
// Set status message based on activity (if we have one) and status is not offline
if (activity != null && !(status is UserStatusOffline))
{
statusMessage.Text = activity.Status;
statusMessage.Text = activity.GetStatus();
statusIcon.FadeColour(activity.GetAppropriateColour(Colours), 500, Easing.OutQuint);
return;
}

View File

@ -7,24 +7,26 @@ using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets;
using osu.Game.Scoring;
using osuTK.Graphics;
namespace osu.Game.Users
{
public abstract class UserActivity
{
public abstract string Status { get; }
public abstract string GetStatus(bool hideIdentifiableInformation = false);
public virtual Color4 GetAppropriateColour(OsuColour colours) => colours.GreenDarker;
public class Modding : UserActivity
{
public override string Status => "Modding a map";
public override string GetStatus(bool hideIdentifiableInformation = false) => "Modding a map";
public override Color4 GetAppropriateColour(OsuColour colours) => colours.PurpleDark;
}
public class ChoosingBeatmap : UserActivity
{
public override string Status => "Choosing a beatmap";
public override string GetStatus(bool hideIdentifiableInformation = false) => "Choosing a beatmap";
}
public abstract class InGame : UserActivity
@ -39,7 +41,7 @@ namespace osu.Game.Users
Ruleset = ruleset;
}
public override string Status => Ruleset.CreateInstance().PlayingVerb;
public override string GetStatus(bool hideIdentifiableInformation = false) => Ruleset.CreateInstance().PlayingVerb;
}
public class InMultiplayerGame : InGame
@ -49,7 +51,7 @@ namespace osu.Game.Users
{
}
public override string Status => $@"{base.Status} with others";
public override string GetStatus(bool hideIdentifiableInformation = false) => $@"{base.GetStatus(hideIdentifiableInformation)} with others";
}
public class SpectatingMultiplayerGame : InGame
@ -59,7 +61,7 @@ namespace osu.Game.Users
{
}
public override string Status => $"Watching others {base.Status.ToLowerInvariant()}";
public override string GetStatus(bool hideIdentifiableInformation = false) => $"Watching others {base.GetStatus(hideIdentifiableInformation).ToLowerInvariant()}";
}
public class InPlaylistGame : InGame
@ -87,22 +89,43 @@ namespace osu.Game.Users
BeatmapInfo = info;
}
public override string Status => @"Editing a beatmap";
public override string GetStatus(bool hideIdentifiableInformation = false) => @"Editing a beatmap";
}
public class Spectating : UserActivity
public class Watching : UserActivity
{
public override string Status => @"Spectating a game";
private readonly ScoreInfo score;
protected string Username => score.User.Username;
public BeatmapInfo BeatmapInfo => score.BeatmapInfo;
public Watching(ScoreInfo score)
{
this.score = score;
}
public override string GetStatus(bool hideIdentifiableInformation = false) => hideIdentifiableInformation ? @"Watching a replay" : $@"Watching {Username}'s replay";
}
public class Spectating : Watching
{
public override string GetStatus(bool hideIdentifiableInformation = false) => hideIdentifiableInformation ? @"Spectating a user" : $@"Spectating {Username}";
public Spectating(ScoreInfo score)
: base(score)
{
}
}
public class SearchingForLobby : UserActivity
{
public override string Status => @"Looking for a lobby";
public override string GetStatus(bool hideIdentifiableInformation = false) => @"Looking for a lobby";
}
public class InLobby : UserActivity
{
public override string Status => @"In a lobby";
public override string GetStatus(bool hideIdentifiableInformation = false) => @"In a lobby";
public readonly Room Room;

View File

@ -18,29 +18,29 @@
</None>
</ItemGroup>
<ItemGroup Label="Package References">
<PackageReference Include="AutoMapper" Version="11.0.1" />
<PackageReference Include="AutoMapper" Version="12.0.1" />
<PackageReference Include="DiffPlex" Version="1.7.1" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.46" />
<PackageReference Include="Humanizer" Version="2.14.1" />
<PackageReference Include="MessagePack" Version="2.4.35" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.10" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="6.0.10" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="6.0.10" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="6.0.10" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
<PackageReference Include="MessagePack" Version="2.4.59" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.2" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="7.0.2" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="7.0.2" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="7.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0" />
<PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.1.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="ppy.LocalisationAnalyser" Version="2022.809.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Realm" Version="10.18.0" />
<PackageReference Include="Realm" Version="10.20.0" />
<PackageReference Include="ppy.osu.Framework" Version="2023.131.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2023.202.0" />
<PackageReference Include="Sentry" Version="3.23.1" />
<PackageReference Include="Sentry" Version="3.28.1" />
<PackageReference Include="SharpCompress" Version="0.32.2" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.2" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.4" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="TagLibSharp" Version="2.3.0" />