diff --git a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs new file mode 100644 index 0000000000..8a98614fa0 --- /dev/null +++ b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs @@ -0,0 +1,95 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Specialized; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Screens; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.Spectator; +using osu.Game.Screens.Play; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Overlays.Dashboard +{ + internal class CurrentlyPlayingDisplay : CompositeDrawable + { + private IBindableList playingUsers; + + private FillFlowContainer userFlow; + + [Resolved] + private SpectatorStreamingClient spectatorStreaming { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + InternalChild = userFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(10), + }; + } + + [Resolved] + private IAPIProvider api { get; set; } + + protected override void LoadComplete() + { + base.LoadComplete(); + + playingUsers = spectatorStreaming.PlayingUsers.GetBoundCopy(); + playingUsers.BindCollectionChanged((sender, e) => Schedule(() => + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + foreach (var u in e.NewItems.OfType()) + { + var request = new GetUserRequest(u); + request.Success += user => Schedule(() => + { + if (playingUsers.Contains((int)user.Id)) + userFlow.Add(createUserPanel(user)); + }); + api.Queue(request); + } + + break; + + case NotifyCollectionChangedAction.Remove: + foreach (var u in e.OldItems.OfType()) + userFlow.FirstOrDefault(card => card.User.Id == u)?.Expire(); + break; + + case NotifyCollectionChangedAction.Reset: + userFlow.Clear(); + break; + } + }), true); + } + + [Resolved] + private OsuGame game { get; set; } + + private UserPanel createUserPanel(User user) + { + return new UserGridPanel(user).With(panel => + { + panel.Anchor = Anchor.TopCentre; + panel.Origin = Anchor.TopCentre; + panel.Width = 290; + panel.Action = () => game.PerformFromScreen(s => s.Push(new Spectator(user))); + }); + } + } +} diff --git a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs index 36bf589877..3314ed957a 100644 --- a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs +++ b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.ComponentModel; + namespace osu.Game.Overlays.Dashboard { public class DashboardOverlayHeader : TabControlOverlayHeader @@ -20,6 +22,9 @@ namespace osu.Game.Overlays.Dashboard public enum DashboardOverlayTabs { - Friends + Friends, + + [Description("Currently Playing")] + CurrentlyPlaying } } diff --git a/osu.Game/Overlays/DashboardOverlay.cs b/osu.Game/Overlays/DashboardOverlay.cs index a2490365e4..04defce636 100644 --- a/osu.Game/Overlays/DashboardOverlay.cs +++ b/osu.Game/Overlays/DashboardOverlay.cs @@ -130,6 +130,10 @@ namespace osu.Game.Overlays loadDisplay(new FriendDisplay()); break; + case DashboardOverlayTabs.CurrentlyPlaying: + loadDisplay(new CurrentlyPlayingDisplay()); + break; + default: throw new NotImplementedException($"Display for {tab.NewValue} tab is not implemented"); }