diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 32a8ba51a3..94804ad1cc 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -54,8 +54,8 @@ namespace osu.Desktop [Resolved] private OsuConfigManager config { get; set; } = null!; - private readonly IBindable status = new Bindable(); - private readonly IBindable activity = new Bindable(); + private readonly IBindable status = new Bindable(); + private readonly IBindable activity = new Bindable(); private readonly Bindable privacyMode = new Bindable(); private readonly RichPresence presence = new RichPresence @@ -108,14 +108,8 @@ namespace osu.Desktop config.BindWith(OsuSetting.DiscordRichPresence, privacyMode); user = api.LocalUser.GetBoundCopy(); - user.BindValueChanged(u => - { - status.UnbindBindings(); - status.BindTo(u.NewValue.Status); - - activity.UnbindBindings(); - activity.BindTo(u.NewValue.Activity); - }, true); + status.BindTo(api.Status); + activity.BindTo(api.Activity); ruleset.BindValueChanged(_ => schedulePresenceUpdate()); status.BindValueChanged(_ => schedulePresenceUpdate()); diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs index 609bc6e166..5c12e0c102 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs @@ -89,7 +89,7 @@ namespace osu.Game.Tests.Visual.Menus AddStep("clear handler", () => dummyAPI.HandleRequest = null); assertDropdownState(UserAction.Online); - AddStep("change user state", () => dummyAPI.LocalUser.Value.Status.Value = UserStatus.DoNotDisturb); + AddStep("change user state", () => dummyAPI.Status.Value = UserStatus.DoNotDisturb); assertDropdownState(UserAction.DoNotDisturb); } diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs index 4539eae25f..fce888094d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserClickableAvatar.cs @@ -62,10 +62,7 @@ namespace osu.Game.Tests.Visual.Online CountryCode = countryCode, CoverUrl = cover, Colour = color ?? "000000", - Status = - { - Value = UserStatus.Online - }, + IsOnline = true }; return new ClickableAvatar(user, showPanel) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index 3f1d961588..4c2e47d336 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.Online Id = 3103765, CountryCode = CountryCode.JP, CoverUrl = @"https://assets.ppy.sh/user-cover-presets/1/df28696b58541a9e67f6755918951d542d93bdf1da41720fcca2fd2c1ea8cf51.jpeg", - Status = { Value = UserStatus.Online } + IsOnline = true }) { Width = 300 }, boundPanel1 = new UserGridPanel(new APIUser { diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 00fe3bb005..4f8c5dcb22 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -60,6 +60,7 @@ namespace osu.Game.Online.API public IBindable LocalUser => localUser; public IBindableList Friends => friends; + public Bindable Status { get; } = new Bindable(UserStatus.Online); public IBindable Activity => activity; public INotificationsClient NotificationsClient { get; } @@ -73,7 +74,6 @@ namespace osu.Game.Online.API private Bindable activity { get; } = new Bindable(); private Bindable configStatus { get; } = new Bindable(); - private Bindable localUserStatus { get; } = new Bindable(); protected bool HasLogin => authentication.Token.Value != null || (!string.IsNullOrEmpty(ProvidedUsername) && !string.IsNullOrEmpty(password)); @@ -121,17 +121,6 @@ namespace osu.Game.Online.API state.Value = APIState.Connecting; } - localUser.BindValueChanged(u => - { - u.OldValue?.Activity.UnbindFrom(activity); - u.NewValue.Activity.BindTo(activity); - - u.OldValue?.Status.UnbindFrom(localUserStatus); - u.NewValue.Status.BindTo(localUserStatus); - }, true); - - localUserStatus.BindTo(configStatus); - var thread = new Thread(run) { Name = "APIAccess", @@ -342,9 +331,8 @@ namespace osu.Game.Online.API { Debug.Assert(ThreadSafety.IsUpdateThread); - me.Status.Value = configStatus.Value ?? UserStatus.Online; - localUser.Value = me; + Status.Value = configStatus.Value ?? UserStatus.Online; state.Value = me.SessionVerified ? APIState.Online : APIState.RequiresSecondFactorAuth; failureCount = 0; @@ -381,9 +369,10 @@ namespace osu.Game.Online.API localUser.Value = new APIUser { - Username = ProvidedUsername, - Status = { Value = configStatus.Value ?? UserStatus.Online } + Username = ProvidedUsername }; + + Status.Value = configStatus.Value ?? UserStatus.Online; } public void Perform(APIRequest request) diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 5d63c04925..b338f4e8cb 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -28,7 +28,9 @@ namespace osu.Game.Online.API public BindableList Friends { get; } = new BindableList(); - public Bindable Activity { get; } = new Bindable(); + public Bindable Status { get; } = new Bindable(UserStatus.Online); + + public Bindable Activity { get; } = new Bindable(); public DummyNotificationsClient NotificationsClient { get; } = new DummyNotificationsClient(); INotificationsClient IAPIProvider.NotificationsClient => NotificationsClient; @@ -69,15 +71,6 @@ namespace osu.Game.Online.API /// public IBindable State => state; - public DummyAPIAccess() - { - LocalUser.BindValueChanged(u => - { - u.OldValue?.Activity.UnbindFrom(Activity); - u.NewValue.Activity.BindTo(Activity); - }, true); - } - public virtual void Queue(APIRequest request) { request.AttachAPI(this); @@ -204,7 +197,7 @@ namespace osu.Game.Online.API IBindable IAPIProvider.LocalUser => LocalUser; IBindableList IAPIProvider.Friends => Friends; - IBindable IAPIProvider.Activity => Activity; + IBindable IAPIProvider.Activity => Activity; /// /// Skip 2FA requirement for next login. diff --git a/osu.Game/Online/API/IAPIProvider.cs b/osu.Game/Online/API/IAPIProvider.cs index 1c4b2da742..cc065a659a 100644 --- a/osu.Game/Online/API/IAPIProvider.cs +++ b/osu.Game/Online/API/IAPIProvider.cs @@ -24,10 +24,15 @@ namespace osu.Game.Online.API /// IBindableList Friends { get; } + /// + /// The current user's status. + /// + Bindable Status { get; } + /// /// The current user's activity. /// - IBindable Activity { get; } + IBindable Activity { get; } /// /// The language supplied by this provider to API requests. diff --git a/osu.Game/Online/API/Requests/Responses/APIUser.cs b/osu.Game/Online/API/Requests/Responses/APIUser.cs index a829484506..30fceab852 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUser.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUser.cs @@ -8,7 +8,6 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using Newtonsoft.Json; -using osu.Framework.Bindables; using osu.Game.Extensions; using osu.Game.Users; @@ -56,10 +55,6 @@ namespace osu.Game.Online.API.Requests.Responses set => countryCodeString = value.ToString(); } - public readonly Bindable Status = new Bindable(); - - public readonly Bindable Activity = new Bindable(); - [JsonProperty(@"profile_colour")] public string Colour; diff --git a/osu.Game/Online/Metadata/OnlineMetadataClient.cs b/osu.Game/Online/Metadata/OnlineMetadataClient.cs index a8a14b1c78..b3204a7cd1 100644 --- a/osu.Game/Online/Metadata/OnlineMetadataClient.cs +++ b/osu.Game/Online/Metadata/OnlineMetadataClient.cs @@ -37,8 +37,9 @@ namespace osu.Game.Online.Metadata private IHubClientConnector? connector; private Bindable lastQueueId = null!; private IBindable localUser = null!; + + private IBindable userStatus = null!; private IBindable userActivity = null!; - private IBindable? userStatus; private HubConnection? connection => connector?.CurrentConnection; @@ -75,22 +76,20 @@ namespace osu.Game.Online.Metadata lastQueueId = config.GetBindable(OsuSetting.LastProcessedMetadataId); localUser = api.LocalUser.GetBoundCopy(); + userStatus = api.Status.GetBoundCopy(); userActivity = api.Activity.GetBoundCopy()!; } protected override void LoadComplete() { base.LoadComplete(); - localUser.BindValueChanged(_ => + + userStatus.BindValueChanged(status => { if (localUser.Value is not GuestUser) - { - userStatus = localUser.Value.Status.GetBoundCopy(); - userStatus.BindValueChanged(status => UpdateStatus(status.NewValue), true); - } - else - userStatus = null; + UpdateStatus(status.NewValue); }, true); + userActivity.BindValueChanged(activity => { if (localUser.Value is not GuestUser) @@ -117,7 +116,7 @@ namespace osu.Game.Online.Metadata if (localUser.Value is not GuestUser) { UpdateActivity(userActivity.Value); - UpdateStatus(userStatus?.Value); + UpdateStatus(userStatus.Value); } if (lastQueueId.Value >= 0) diff --git a/osu.Game/Overlays/Dashboard/CurrentlyOnlineDisplay.cs b/osu.Game/Overlays/Dashboard/CurrentlyOnlineDisplay.cs index ee277ff538..2ca548fdf5 100644 --- a/osu.Game/Overlays/Dashboard/CurrentlyOnlineDisplay.cs +++ b/osu.Game/Overlays/Dashboard/CurrentlyOnlineDisplay.cs @@ -140,15 +140,11 @@ namespace osu.Game.Overlays.Dashboard Schedule(() => { - // explicitly refetch the user's status. - // things may have changed in between the time of scheduling and the time of actual execution. - if (onlineUsers.TryGetValue(userId, out var updatedStatus)) + userFlow.Add(userPanels[userId] = createUserPanel(user).With(p => { - user.Activity.Value = updatedStatus.Activity; - user.Status.Value = updatedStatus.Status; - } - - userFlow.Add(userPanels[userId] = createUserPanel(user)); + p.Status.Value = onlineUsers.GetValueOrDefault(userId).Status; + p.Activity.Value = onlineUsers.GetValueOrDefault(userId).Activity; + })); }); }); } @@ -162,8 +158,8 @@ namespace osu.Game.Overlays.Dashboard { if (userPanels.TryGetValue(kvp.Key, out var panel)) { - panel.User.Activity.Value = kvp.Value.Activity; - panel.User.Status.Value = kvp.Value.Status; + panel.Activity.Value = kvp.Value.Activity; + panel.Status.Value = kvp.Value.Status; } } @@ -223,6 +219,9 @@ namespace osu.Game.Overlays.Dashboard { public readonly APIUser User; + public readonly Bindable Status = new Bindable(); + public readonly Bindable Activity = new Bindable(); + public BindableBool CanSpectate { get; } = new BindableBool(); public IEnumerable FilterTerms { get; } @@ -271,8 +270,8 @@ namespace osu.Game.Overlays.Dashboard Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, // this is SHOCKING - Activity = { BindTarget = User.Activity }, - Status = { BindTarget = User.Status }, + Activity = { BindTarget = Activity }, + Status = { BindTarget = Status }, }, new PurpleRoundedButton { diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 84bd0c36b9..b947731f8b 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -15,7 +15,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; using osu.Game.Online.API; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Settings; using osu.Game.Users; using osuTK; @@ -38,9 +37,7 @@ namespace osu.Game.Overlays.Login /// public Action? RequestHide; - private IBindable user = null!; - private readonly Bindable status = new Bindable(); - + private readonly Bindable status = new Bindable(); private readonly IBindable apiState = new Bindable(); [Resolved] @@ -71,13 +68,7 @@ namespace osu.Game.Overlays.Login apiState.BindTo(api.State); apiState.BindValueChanged(onlineStateChanged, true); - user = api.LocalUser.GetBoundCopy(); - user.BindValueChanged(u => - { - status.UnbindBindings(); - status.BindTo(u.NewValue.Status); - }, true); - + status.BindTo(api.Status); status.BindValueChanged(e => updateDropdownCurrent(e.NewValue), true); } @@ -163,17 +154,17 @@ namespace osu.Game.Overlays.Login switch (action.NewValue) { case UserAction.Online: - api.LocalUser.Value.Status.Value = UserStatus.Online; + status.Value = UserStatus.Online; dropdown.StatusColour = colours.Green; break; case UserAction.DoNotDisturb: - api.LocalUser.Value.Status.Value = UserStatus.DoNotDisturb; + status.Value = UserStatus.DoNotDisturb; dropdown.StatusColour = colours.Red; break; case UserAction.AppearOffline: - api.LocalUser.Value.Status.Value = UserStatus.Offline; + status.Value = UserStatus.Offline; dropdown.StatusColour = colours.Gray7; break;