diff --git a/osu.Game/Overlays/Social/FilterControl.cs b/osu.Game/Overlays/Social/FilterControl.cs index cf4097643e..03acd9bf13 100644 --- a/osu.Game/Overlays/Social/FilterControl.cs +++ b/osu.Game/Overlays/Social/FilterControl.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Social public enum SocialSortCriteria { Rank, - //Location, + Location, //[Description("Time Zone")] //TimeZone, //[Description("World Map")] diff --git a/osu.Game/Overlays/Social/Header.cs b/osu.Game/Overlays/Social/Header.cs index 2674854327..e15b16085b 100644 --- a/osu.Game/Overlays/Social/Header.cs +++ b/osu.Game/Overlays/Social/Header.cs @@ -55,8 +55,8 @@ namespace osu.Game.Overlays.Social { [Description("Online Players")] OnlinePlayers, - //[Description("Online Friends")] - //OnlineFriends, + [Description("Online Friends")] + OnlineFriends, //[Description("Online Team Members")] //OnlineTeamMembers, //[Description("Chat Channels")] diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 954a838461..84469c5e40 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -9,19 +9,23 @@ using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; -using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.Social; using osu.Game.Users; +using osu.Framework.Configuration; +using osu.Framework.Threading; +using System.Threading.Tasks; namespace osu.Game.Overlays { - public class SocialOverlay : SearchableListOverlay, IOnlineComponent + public class SocialOverlay : SearchableListOverlay { - private readonly FillFlowContainer panelFlow; + private APIAccess api; + + private FillFlowContainer panels; protected override Color4 BackgroundColour => OsuColour.FromHex(@"60284b"); protected override Color4 TrianglesColourLight => OsuColour.FromHex(@"672b51"); @@ -30,28 +34,19 @@ namespace osu.Game.Overlays protected override SearchableListHeader CreateHeader() => new Header(); protected override SearchableListFilterControl CreateFilterControl() => new FilterControl(); - private IEnumerable users; private readonly LoadingAnimation loading; + private IEnumerable users; + public IEnumerable Users { get { return users; } set { - if (users?.Equals(value) ?? false) return; - users = value; + if (users?.Equals(value) ?? false) + return; - if (users == null) - panelFlow.Clear(); - else - { - panelFlow.ChildrenEnumerable = users.Select(u => - { - var p = new UserPanel(u) { Width = 300 }; - p.Status.BindTo(u.Status); - return p; - }); - } + users = value?.ToList(); } } @@ -62,59 +57,129 @@ namespace osu.Game.Overlays ThirdWaveColour = OsuColour.FromHex(@"9b2b6e"); FourthWaveColour = OsuColour.FromHex(@"6d214d"); - ScrollFlow.Children = new[] + Add(loading = new LoadingAnimation()); + + Filter.DisplayStyleControl.DisplayStyle.ValueChanged += recreatePanels; + + // TODO sort our list in some way (either locally or with API call) + //Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += rankStatus => Scheduler.AddOnce(updateSearch); + + Header.Tabs.Current.ValueChanged += tab => { - new OsuContextMenuContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = panelFlow = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = 20 }, - Spacing = new Vector2(10f), - } - }, + currentQuery.Value = string.Empty; + Filter.Tabs.Current.Value = (SocialSortCriteria)Header.Tabs.Current.Value; + Scheduler.AddOnce(updateSearch); }; - Add(loading = new LoadingAnimation()); + currentQuery.ValueChanged += v => + { + queryChangedDebounce?.Cancel(); + + if (string.IsNullOrEmpty(v)) + Scheduler.AddOnce(updateSearch); + else + { + Users = null; + queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); + } + }; + + currentQuery.BindTo(Filter.Search.Current); + + Filter.Tabs.Current.ValueChanged += sortCriteria => Scheduler.AddOnce(updateSearch); + + Scheduler.AddOnce(updateSearch); // so it displays something once it's first opened } [BackgroundDependencyLoader] private void load(APIAccess api) { - if (Users == null) - reloadUsers(api); + this.api = api; } - private void reloadUsers(APIAccess api) + private void recreatePanels(PanelDisplayStyle displayStyle) { - Users = null; + if (Users == null) + return; - // no this is not the correct data source, but it's something. - var request = new GetUsersRequest(); - request.Success += res => + if (panels != null) { - Users = res.Select(e => e.User); - loading.Hide(); + panels.FadeOut(200); + panels.Expire(); + panels = null; + } + + var newPanels = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(10f), + Margin = new MarginPadding { Top = 10 }, + ChildrenEnumerable = Users.Select(u => + { + UserPanel panel = new UserPanel(u); + switch (displayStyle) + { + case PanelDisplayStyle.Grid: + panel.Width = 300; + break; + default: + panel.RelativeSizeAxes = Axes.X; + break; + } + panel.Status.BindTo(u.Status); + return panel; + }) }; - api.Queue(request); - loading.Show(); + LoadComponentAsync(newPanels, p => + { + if (panels != null) + ScrollFlow.Remove(panels); + + ScrollFlow.Add(panels = newPanels); + }); } - public void APIStateChanged(APIAccess api, APIState state) + private GetUsersRequest getUsersRequest; + + private readonly Bindable currentQuery = new Bindable(); + + private ScheduledDelegate queryChangedDebounce; + + private void updateSearch() { - switch (state) + queryChangedDebounce?.Cancel(); + + if (!IsLoaded) + return; + + Users = null; + loading.Hide(); + getUsersRequest?.Cancel(); + + if (api == null || api.State == APIState.Offline) + return; + + getUsersRequest = new GetUsersRequest(); // TODO filter/sort values?!? + + getUsersRequest.Success += response => { - case APIState.Online: - reloadUsers(api); - break; - default: - Users = null; - break; - } + Task.Run(() => + { + var newUsers = response.Select(r => r.User); + + Schedule(() => + { + Users = newUsers; + recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); + loading.Hide(); + }); + }); + }; + + loading.Show(); + api.Queue(getUsersRequest); } }