1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-04 02:32:56 +08:00

Move bindables to OsuConfigManager & SessionStatics

This commit is contained in:
Dan Balasescu 2025-01-16 19:33:38 +09:00
parent c1f0c47586
commit 8400726887
No known key found for this signature in database
11 changed files with 67 additions and 61 deletions

View File

@ -51,12 +51,9 @@ namespace osu.Desktop
[Resolved] [Resolved]
private LocalUserStatisticsProvider statisticsProvider { get; set; } = null!; private LocalUserStatisticsProvider statisticsProvider { get; set; } = null!;
[Resolved] private IBindable<DiscordRichPresenceMode> privacyMode = null!;
private OsuConfigManager config { get; set; } = null!; private IBindable<UserStatus> userStatus = null!;
private IBindable<UserActivity?> userActivity = null!;
private readonly IBindable<UserStatus> status = new Bindable<UserStatus>();
private readonly IBindable<UserActivity?> activity = new Bindable<UserActivity?>();
private readonly Bindable<DiscordRichPresenceMode> privacyMode = new Bindable<DiscordRichPresenceMode>();
private readonly RichPresence presence = new RichPresence private readonly RichPresence presence = new RichPresence
{ {
@ -71,8 +68,12 @@ namespace osu.Desktop
private IBindable<APIUser>? user; private IBindable<APIUser>? user;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load(OsuConfigManager config, SessionStatics session)
{ {
privacyMode = config.GetBindable<DiscordRichPresenceMode>(OsuSetting.DiscordRichPresence);
userStatus = config.GetBindable<UserStatus>(OsuSetting.UserOnlineStatus);
userActivity = session.GetBindable<UserActivity?>(Static.UserOnlineActivity);
client = new DiscordRpcClient(client_id) client = new DiscordRpcClient(client_id)
{ {
// SkipIdenticalPresence allows us to fire SetPresence at any point and leave it to the underlying implementation // SkipIdenticalPresence allows us to fire SetPresence at any point and leave it to the underlying implementation
@ -105,15 +106,11 @@ namespace osu.Desktop
{ {
base.LoadComplete(); base.LoadComplete();
config.BindWith(OsuSetting.DiscordRichPresence, privacyMode);
user = api.LocalUser.GetBoundCopy(); user = api.LocalUser.GetBoundCopy();
status.BindTo(api.Status);
activity.BindTo(api.Activity);
ruleset.BindValueChanged(_ => schedulePresenceUpdate()); ruleset.BindValueChanged(_ => schedulePresenceUpdate());
status.BindValueChanged(_ => schedulePresenceUpdate()); userStatus.BindValueChanged(_ => schedulePresenceUpdate());
activity.BindValueChanged(_ => schedulePresenceUpdate()); userActivity.BindValueChanged(_ => schedulePresenceUpdate());
privacyMode.BindValueChanged(_ => schedulePresenceUpdate()); privacyMode.BindValueChanged(_ => schedulePresenceUpdate());
multiplayerClient.RoomUpdated += onRoomUpdated; multiplayerClient.RoomUpdated += onRoomUpdated;
@ -145,13 +142,13 @@ namespace osu.Desktop
if (!client.IsInitialized) if (!client.IsInitialized)
return; return;
if (!api.IsLoggedIn || status.Value == UserStatus.Offline || privacyMode.Value == DiscordRichPresenceMode.Off) if (!api.IsLoggedIn || userStatus.Value == UserStatus.Offline || privacyMode.Value == DiscordRichPresenceMode.Off)
{ {
client.ClearPresence(); client.ClearPresence();
return; return;
} }
bool hideIdentifiableInformation = privacyMode.Value == DiscordRichPresenceMode.Limited || status.Value == UserStatus.DoNotDisturb; bool hideIdentifiableInformation = privacyMode.Value == DiscordRichPresenceMode.Limited || userStatus.Value == UserStatus.DoNotDisturb;
updatePresence(hideIdentifiableInformation); updatePresence(hideIdentifiableInformation);
client.SetPresence(presence); client.SetPresence(presence);
@ -164,12 +161,12 @@ namespace osu.Desktop
return; return;
// user activity // user activity
if (activity.Value != null) if (userActivity.Value != null)
{ {
presence.State = clampLength(activity.Value.GetStatus(hideIdentifiableInformation)); presence.State = clampLength(userActivity.Value.GetStatus(hideIdentifiableInformation));
presence.Details = clampLength(activity.Value.GetDetails(hideIdentifiableInformation) ?? string.Empty); presence.Details = clampLength(userActivity.Value.GetDetails(hideIdentifiableInformation) ?? string.Empty);
if (activity.Value.GetBeatmapID(hideIdentifiableInformation) is int beatmapId && beatmapId > 0) if (userActivity.Value.GetBeatmapID(hideIdentifiableInformation) is int beatmapId && beatmapId > 0)
{ {
presence.Buttons = new[] presence.Buttons = new[]
{ {

View File

@ -8,7 +8,7 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Online.API; using osu.Game.Configuration;
using osu.Game.Online.Chat; using osu.Game.Online.Chat;
using osu.Game.Online.Rooms; using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
@ -23,17 +23,23 @@ namespace osu.Game.Tests.Visual.Online
[Cached(typeof(IChannelPostTarget))] [Cached(typeof(IChannelPostTarget))]
private PostTarget postTarget { get; set; } private PostTarget postTarget { get; set; }
private DummyAPIAccess api => (DummyAPIAccess)API; private SessionStatics session = null!;
public TestSceneNowPlayingCommand() public TestSceneNowPlayingCommand()
{ {
Add(postTarget = new PostTarget()); Add(postTarget = new PostTarget());
} }
[BackgroundDependencyLoader]
private void load()
{
Dependencies.Cache(session = new SessionStatics());
}
[Test] [Test]
public void TestGenericActivity() public void TestGenericActivity()
{ {
AddStep("Set activity", () => api.Activity.Value = new UserActivity.InLobby(new Room())); AddStep("Set activity", () => session.SetValue(Static.UserOnlineActivity, new UserActivity.InLobby(new Room())));
AddStep("Run command", () => Add(new NowPlayingCommand(new Channel()))); AddStep("Run command", () => Add(new NowPlayingCommand(new Channel())));
@ -43,7 +49,7 @@ namespace osu.Game.Tests.Visual.Online
[Test] [Test]
public void TestEditActivity() public void TestEditActivity()
{ {
AddStep("Set activity", () => api.Activity.Value = new UserActivity.EditingBeatmap(new BeatmapInfo())); AddStep("Set activity", () => session.SetValue(Static.UserOnlineActivity, new UserActivity.EditingBeatmap(new BeatmapInfo())));
AddStep("Run command", () => Add(new NowPlayingCommand(new Channel()))); AddStep("Run command", () => Add(new NowPlayingCommand(new Channel())));
@ -53,7 +59,7 @@ namespace osu.Game.Tests.Visual.Online
[Test] [Test]
public void TestPlayActivity() public void TestPlayActivity()
{ {
AddStep("Set activity", () => api.Activity.Value = new UserActivity.InSoloGame(new BeatmapInfo(), new OsuRuleset().RulesetInfo)); AddStep("Set activity", () => session.SetValue(Static.UserOnlineActivity, new UserActivity.InSoloGame(new BeatmapInfo(), new OsuRuleset().RulesetInfo)));
AddStep("Run command", () => Add(new NowPlayingCommand(new Channel()))); AddStep("Run command", () => Add(new NowPlayingCommand(new Channel())));
@ -64,7 +70,7 @@ namespace osu.Game.Tests.Visual.Online
[TestCase(false)] [TestCase(false)]
public void TestLinkPresence(bool hasOnlineId) public void TestLinkPresence(bool hasOnlineId)
{ {
AddStep("Set activity", () => api.Activity.Value = new UserActivity.InLobby(new Room())); AddStep("Set activity", () => session.SetValue(Static.UserOnlineActivity, new UserActivity.InLobby(new Room())));
AddStep("Set beatmap", () => Beatmap.Value = new DummyWorkingBeatmap(Audio, null) AddStep("Set beatmap", () => Beatmap.Value = new DummyWorkingBeatmap(Audio, null)
{ {
@ -82,7 +88,7 @@ namespace osu.Game.Tests.Visual.Online
[Test] [Test]
public void TestModPresence() public void TestModPresence()
{ {
AddStep("Set activity", () => api.Activity.Value = new UserActivity.InSoloGame(new BeatmapInfo(), new OsuRuleset().RulesetInfo)); AddStep("Set activity", () => session.SetValue(Static.UserOnlineActivity, new UserActivity.InSoloGame(new BeatmapInfo(), new OsuRuleset().RulesetInfo)));
AddStep("Add Hidden mod", () => SelectedMods.Value = new[] { Ruleset.Value.CreateInstance().CreateMod<ModHidden>() }); AddStep("Add Hidden mod", () => SelectedMods.Value = new[] { Ruleset.Value.CreateInstance().CreateMod<ModHidden>() });

View File

@ -10,6 +10,7 @@ using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Overlays.Mods; using osu.Game.Overlays.Mods;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Users;
namespace osu.Game.Configuration namespace osu.Game.Configuration
{ {
@ -30,6 +31,7 @@ namespace osu.Game.Configuration
SetDefault(Static.TouchInputActive, RuntimeInfo.IsMobile); SetDefault(Static.TouchInputActive, RuntimeInfo.IsMobile);
SetDefault<ScoreInfo>(Static.LastLocalUserScore, null); SetDefault<ScoreInfo>(Static.LastLocalUserScore, null);
SetDefault<ScoreInfo>(Static.LastAppliedOffsetScore, null); SetDefault<ScoreInfo>(Static.LastAppliedOffsetScore, null);
SetDefault<UserActivity>(Static.UserOnlineActivity, null);
} }
/// <summary> /// <summary>
@ -92,5 +94,7 @@ namespace osu.Game.Configuration
/// This is reset when a new challenge is up. /// This is reset when a new challenge is up.
/// </summary> /// </summary>
DailyChallengeIntroPlayed, DailyChallengeIntroPlayed,
UserOnlineActivity,
} }
} }

View File

@ -60,8 +60,6 @@ namespace osu.Game.Online.API
public IBindable<APIUser> LocalUser => localUser; public IBindable<APIUser> LocalUser => localUser;
public IBindableList<APIRelation> Friends => friends; public IBindableList<APIRelation> Friends => friends;
public IBindable<UserStatus> Status => configStatus;
public IBindable<UserActivity> Activity => activity;
public INotificationsClient NotificationsClient { get; } public INotificationsClient NotificationsClient { get; }
@ -71,8 +69,6 @@ namespace osu.Game.Online.API
private BindableList<APIRelation> friends { get; } = new BindableList<APIRelation>(); private BindableList<APIRelation> friends { get; } = new BindableList<APIRelation>();
private Bindable<UserActivity> activity { get; } = new Bindable<UserActivity>();
protected bool HasLogin => authentication.Token.Value != null || (!string.IsNullOrEmpty(ProvidedUsername) && !string.IsNullOrEmpty(password)); protected bool HasLogin => authentication.Token.Value != null || (!string.IsNullOrEmpty(ProvidedUsername) && !string.IsNullOrEmpty(password));
private readonly Bindable<UserStatus> configStatus = new Bindable<UserStatus>(); private readonly Bindable<UserStatus> configStatus = new Bindable<UserStatus>();

View File

@ -12,7 +12,6 @@ using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Chat; using osu.Game.Online.Chat;
using osu.Game.Online.Notifications.WebSocket; using osu.Game.Online.Notifications.WebSocket;
using osu.Game.Tests; using osu.Game.Tests;
using osu.Game.Users;
namespace osu.Game.Online.API namespace osu.Game.Online.API
{ {
@ -28,10 +27,6 @@ namespace osu.Game.Online.API
public BindableList<APIRelation> Friends { get; } = new BindableList<APIRelation>(); public BindableList<APIRelation> Friends { get; } = new BindableList<APIRelation>();
public Bindable<UserStatus> Status { get; } = new Bindable<UserStatus>(UserStatus.Online);
public Bindable<UserActivity?> Activity { get; } = new Bindable<UserActivity?>();
public DummyNotificationsClient NotificationsClient { get; } = new DummyNotificationsClient(); public DummyNotificationsClient NotificationsClient { get; } = new DummyNotificationsClient();
INotificationsClient IAPIProvider.NotificationsClient => NotificationsClient; INotificationsClient IAPIProvider.NotificationsClient => NotificationsClient;
@ -197,8 +192,6 @@ namespace osu.Game.Online.API
IBindable<APIUser> IAPIProvider.LocalUser => LocalUser; IBindable<APIUser> IAPIProvider.LocalUser => LocalUser;
IBindableList<APIRelation> IAPIProvider.Friends => Friends; IBindableList<APIRelation> IAPIProvider.Friends => Friends;
IBindable<UserStatus> IAPIProvider.Status => Status;
IBindable<UserActivity?> IAPIProvider.Activity => Activity;
/// <summary> /// <summary>
/// Skip 2FA requirement for next login. /// Skip 2FA requirement for next login.

View File

@ -8,7 +8,6 @@ using osu.Game.Localisation;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Chat; using osu.Game.Online.Chat;
using osu.Game.Online.Notifications.WebSocket; using osu.Game.Online.Notifications.WebSocket;
using osu.Game.Users;
namespace osu.Game.Online.API namespace osu.Game.Online.API
{ {
@ -24,16 +23,6 @@ namespace osu.Game.Online.API
/// </summary> /// </summary>
IBindableList<APIRelation> Friends { get; } IBindableList<APIRelation> Friends { get; }
/// <summary>
/// The status for the current user that's broadcast to other players.
/// </summary>
IBindable<UserStatus> Status { get; }
/// <summary>
/// The activity for the current user that's broadcast to other players.
/// </summary>
IBindable<UserActivity?> Activity { get; }
/// <summary> /// <summary>
/// The language supplied by this provider to API requests. /// The language supplied by this provider to API requests.
/// </summary> /// </summary>

View File

@ -8,6 +8,7 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
@ -33,6 +34,7 @@ namespace osu.Game.Online.Chat
private IBindable<RulesetInfo> currentRuleset { get; set; } = null!; private IBindable<RulesetInfo> currentRuleset { get; set; } = null!;
private readonly Channel? target; private readonly Channel? target;
private IBindable<UserActivity?> userActivity = null!;
/// <summary> /// <summary>
/// Creates a new <see cref="NowPlayingCommand"/> to post the currently-playing beatmap to a parenting <see cref="IChannelPostTarget"/>. /// Creates a new <see cref="NowPlayingCommand"/> to post the currently-playing beatmap to a parenting <see cref="IChannelPostTarget"/>.
@ -43,6 +45,12 @@ namespace osu.Game.Online.Chat
this.target = target; this.target = target;
} }
[BackgroundDependencyLoader]
private void load(SessionStatics session)
{
userActivity = session.GetBindable<UserActivity?>(Static.UserOnlineActivity);
}
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
@ -52,7 +60,7 @@ namespace osu.Game.Online.Chat
int beatmapOnlineID; int beatmapOnlineID;
string beatmapDisplayTitle; string beatmapDisplayTitle;
switch (api.Activity.Value) switch (userActivity.Value)
{ {
case UserActivity.InGame game: case UserActivity.InGame game:
verb = "playing"; verb = "playing";
@ -92,14 +100,14 @@ namespace osu.Game.Online.Chat
string getRulesetPart() string getRulesetPart()
{ {
if (api.Activity.Value is not UserActivity.InGame) return string.Empty; if (userActivity.Value is not UserActivity.InGame) return string.Empty;
return $"<{currentRuleset.Value.Name}>"; return $"<{currentRuleset.Value.Name}>";
} }
string getModPart() string getModPart()
{ {
if (api.Activity.Value is not UserActivity.InGame) return string.Empty; if (userActivity.Value is not UserActivity.InGame) return string.Empty;
if (selectedMods.Value.Count == 0) if (selectedMods.Value.Count == 0)
{ {

View File

@ -34,6 +34,9 @@ namespace osu.Game.Online.Metadata
private readonly string endpoint; private readonly string endpoint;
[Resolved]
private IAPIProvider api { get; set; } = null!;
private IHubClientConnector? connector; private IHubClientConnector? connector;
private Bindable<int> lastQueueId = null!; private Bindable<int> lastQueueId = null!;
private IBindable<APIUser> localUser = null!; private IBindable<APIUser> localUser = null!;
@ -48,7 +51,7 @@ namespace osu.Game.Online.Metadata
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(IAPIProvider api, OsuConfigManager config) private void load(OsuConfigManager config, SessionStatics session)
{ {
// Importantly, we are intentionally not using MessagePack here to correctly support derived class serialization. // Importantly, we are intentionally not using MessagePack here to correctly support derived class serialization.
// More information on the limitations / reasoning can be found in osu-server-spectator's initialisation code. // More information on the limitations / reasoning can be found in osu-server-spectator's initialisation code.
@ -72,11 +75,10 @@ namespace osu.Game.Online.Metadata
IsConnected.BindValueChanged(isConnectedChanged, true); IsConnected.BindValueChanged(isConnectedChanged, true);
} }
lastQueueId = config.GetBindable<int>(OsuSetting.LastProcessedMetadataId);
localUser = api.LocalUser.GetBoundCopy(); localUser = api.LocalUser.GetBoundCopy();
userStatus = api.Status.GetBoundCopy(); lastQueueId = config.GetBindable<int>(OsuSetting.LastProcessedMetadataId);
userActivity = api.Activity.GetBoundCopy()!; userStatus = config.GetBindable<UserStatus>(OsuSetting.UserOnlineStatus);
userActivity = session.GetBindable<UserActivity?>(Static.UserOnlineActivity);
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -240,7 +242,14 @@ namespace osu.Game.Online.Metadata
throw new OperationCanceledException(); throw new OperationCanceledException();
// must be scheduled before any remote calls to avoid mis-ordering. // must be scheduled before any remote calls to avoid mis-ordering.
Schedule(() => userStates.Clear()); Schedule(() =>
{
bool hadLocalUserState = userStates.TryGetValue(api.LocalUser.Value.OnlineID, out var presence);
userStates.Clear();
if (hadLocalUserState)
userStates[api.LocalUser.Value.OnlineID] = presence;
});
Debug.Assert(connection != null); Debug.Assert(connection != null);
await connection.InvokeAsync(nameof(IMetadataServer.EndWatchingUserPresence)).ConfigureAwait(false); await connection.InvokeAsync(nameof(IMetadataServer.EndWatchingUserPresence)).ConfigureAwait(false);
Logger.Log($@"{nameof(OnlineMetadataClient)} stopped watching user presence", LoggingTarget.Network); Logger.Log($@"{nameof(OnlineMetadataClient)} stopped watching user presence", LoggingTarget.Network);

View File

@ -211,6 +211,8 @@ namespace osu.Game
private Bindable<float> uiScale; private Bindable<float> uiScale;
private Bindable<UserActivity> configUserActivity;
private Bindable<string> configSkin; private Bindable<string> configSkin;
private readonly string[] args; private readonly string[] args;
@ -391,6 +393,8 @@ namespace osu.Game
Ruleset.ValueChanged += r => configRuleset.Value = r.NewValue.ShortName; Ruleset.ValueChanged += r => configRuleset.Value = r.NewValue.ShortName;
configUserActivity = SessionStatics.GetBindable<UserActivity>(Static.UserOnlineActivity);
configSkin = LocalConfig.GetBindable<string>(OsuSetting.Skin); configSkin = LocalConfig.GetBindable<string>(OsuSetting.Skin);
// Transfer skin from config to realm instance once on startup. // Transfer skin from config to realm instance once on startup.
@ -1588,14 +1592,14 @@ namespace osu.Game
{ {
backButtonVisibility.UnbindFrom(currentOsuScreen.BackButtonVisibility); backButtonVisibility.UnbindFrom(currentOsuScreen.BackButtonVisibility);
OverlayActivationMode.UnbindFrom(currentOsuScreen.OverlayActivationMode); OverlayActivationMode.UnbindFrom(currentOsuScreen.OverlayActivationMode);
API.Activity.UnbindFrom(currentOsuScreen.Activity); configUserActivity.UnbindFrom(currentOsuScreen.Activity);
} }
if (newScreen is IOsuScreen newOsuScreen) if (newScreen is IOsuScreen newOsuScreen)
{ {
backButtonVisibility.BindTo(newOsuScreen.BackButtonVisibility); backButtonVisibility.BindTo(newOsuScreen.BackButtonVisibility);
OverlayActivationMode.BindTo(newOsuScreen.OverlayActivationMode); OverlayActivationMode.BindTo(newOsuScreen.OverlayActivationMode);
API.Activity.BindTo(newOsuScreen.Activity); configUserActivity.BindTo(newOsuScreen.Activity);
GlobalCursorDisplay.MenuCursor.HideCursorOnNonMouseInput = newOsuScreen.HideMenuCursorOnNonMouseInput; GlobalCursorDisplay.MenuCursor.HideCursorOnNonMouseInput = newOsuScreen.HideMenuCursorOnNonMouseInput;

View File

@ -74,7 +74,7 @@ namespace osu.Game.Screens
/// <summary> /// <summary>
/// The current <see cref="UserActivity"/> for this screen. /// The current <see cref="UserActivity"/> for this screen.
/// </summary> /// </summary>
IBindable<UserActivity> Activity { get; } Bindable<UserActivity> Activity { get; }
/// <summary> /// <summary>
/// The amount of parallax to be applied while this screen is displayed. /// The amount of parallax to be applied while this screen is displayed.

View File

@ -81,7 +81,7 @@ namespace osu.Game.Screens
/// </summary> /// </summary>
protected readonly Bindable<UserActivity> Activity = new Bindable<UserActivity>(); protected readonly Bindable<UserActivity> Activity = new Bindable<UserActivity>();
IBindable<UserActivity> IOsuScreen.Activity => Activity; Bindable<UserActivity> IOsuScreen.Activity => Activity;
/// <summary> /// <summary>
/// Whether to disallow changes to game-wise Beatmap/Ruleset bindables for this screen (and all children). /// Whether to disallow changes to game-wise Beatmap/Ruleset bindables for this screen (and all children).