osu/osu.Game/Overlays/SocialOverlay.cs

243 lines
7.5 KiB
C#
Raw Normal View History

// 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.
2018-04-13 09:19:50 +00:00
2019-12-18 17:02:57 +00:00
using System;
2018-04-13 09:19:50 +00:00
using System.Collections.Generic;
using System.Linq;
2019-02-21 10:04:31 +00:00
using osu.Framework.Bindables;
2018-11-20 07:51:59 +00:00
using osuTK;
using osuTK.Graphics;
2018-04-13 09:19:50 +00:00
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
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 System.Threading;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Threading;
2018-04-13 09:19:50 +00:00
namespace osu.Game.Overlays
{
2019-05-14 05:18:06 +00:00
public class SocialOverlay : SearchableListOverlay<SocialTab, SocialSortCriteria, SortDirection>
2018-04-13 09:19:50 +00:00
{
private readonly LoadingSpinner loading;
2020-03-04 11:58:15 +00:00
private FillFlowContainer<UserPanel> panels;
2018-04-13 09:19:50 +00:00
protected override Color4 BackgroundColour => Color4Extensions.FromHex(@"60284b");
protected override Color4 TrianglesColourLight => Color4Extensions.FromHex(@"672b51");
protected override Color4 TrianglesColourDark => Color4Extensions.FromHex(@"5c2648");
2018-04-13 09:19:50 +00:00
protected override SearchableListHeader<SocialTab> CreateHeader() => new Header();
protected override SearchableListFilterControl<SocialSortCriteria, SortDirection> CreateFilterControl() => new FilterControl();
2019-12-18 17:02:57 +00:00
private User[] users = Array.Empty<User>();
2019-02-28 04:31:40 +00:00
2019-12-18 17:02:57 +00:00
public User[] Users
2018-04-13 09:19:50 +00:00
{
get => users;
2018-04-13 09:19:50 +00:00
set
{
2019-12-18 17:02:57 +00:00
if (users == value)
2018-04-13 09:19:50 +00:00
return;
2019-12-18 17:02:57 +00:00
users = value ?? Array.Empty<User>();
if (LoadState >= LoadState.Ready)
recreatePanels();
2018-04-13 09:19:50 +00:00
}
}
public SocialOverlay()
2020-01-24 09:24:35 +00:00
: base(OverlayColourScheme.Pink)
2018-04-13 09:19:50 +00:00
{
Add(loading = new LoadingSpinner());
2018-04-13 09:19:50 +00:00
Filter.Search.Current.ValueChanged += text =>
2018-04-13 09:19:50 +00:00
{
if (!string.IsNullOrEmpty(text.NewValue))
2018-04-13 09:19:50 +00:00
{
// force searching in players until searching for friends is supported
Header.Tabs.Current.Value = SocialTab.AllPlayers;
if (Filter.Tabs.Current.Value != SocialSortCriteria.Rank)
Filter.Tabs.Current.Value = SocialSortCriteria.Rank;
}
};
Header.Tabs.Current.ValueChanged += _ => queueUpdate();
Filter.Tabs.Current.ValueChanged += _ => onFilterUpdate();
2018-04-13 09:19:50 +00:00
2019-12-18 17:02:57 +00:00
Filter.DisplayStyleControl.DisplayStyle.ValueChanged += _ => recreatePanels();
Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => recreatePanels();
2018-04-13 09:19:50 +00:00
currentQuery.BindTo(Filter.Search.Current);
currentQuery.ValueChanged += query =>
2018-04-13 09:19:50 +00:00
{
queryChangedDebounce?.Cancel();
2018-04-13 09:19:50 +00:00
if (string.IsNullOrEmpty(query.NewValue))
queueUpdate();
2018-04-13 09:19:50 +00:00
else
queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500);
2018-04-13 09:19:50 +00:00
};
}
2018-04-13 09:19:50 +00:00
[BackgroundDependencyLoader]
private void load()
{
recreatePanels();
}
private APIRequest getUsersRequest;
private readonly Bindable<string> currentQuery = new Bindable<string>();
private ScheduledDelegate queryChangedDebounce;
private void queueUpdate() => Scheduler.AddOnce(updateSearch);
private CancellationTokenSource loadCancellation;
private void updateSearch()
{
queryChangedDebounce?.Cancel();
if (!IsLoaded)
return;
Users = null;
clearPanels();
getUsersRequest?.Cancel();
if (API?.IsLoggedIn != true)
return;
switch (Header.Tabs.Current.Value)
{
case SocialTab.Friends:
var friendRequest = new GetFriendsRequest(); // TODO filter arguments?
2019-12-18 17:02:57 +00:00
friendRequest.Success += users => Users = users.ToArray();
API.Queue(getUsersRequest = friendRequest);
break;
default:
var userRequest = new GetUsersRequest(); // TODO filter arguments!
2019-12-18 17:02:57 +00:00
userRequest.Success += res => Users = res.Users.Select(r => r.User).ToArray();
API.Queue(getUsersRequest = userRequest);
break;
}
2018-04-13 09:19:50 +00:00
}
2019-12-18 17:02:57 +00:00
private void recreatePanels()
2018-04-13 09:19:50 +00:00
{
clearPanels();
if (Users == null)
2019-08-27 00:53:16 +00:00
{
loading.Hide();
2018-04-13 09:19:50 +00:00
return;
2019-08-27 00:53:16 +00:00
}
2018-04-13 09:19:50 +00:00
2019-12-18 17:02:57 +00:00
IEnumerable<User> sortedUsers = Users;
switch (Filter.Tabs.Current.Value)
{
case SocialSortCriteria.Location:
sortedUsers = sortedUsers.OrderBy(u => u.Country.FullName);
break;
case SocialSortCriteria.Name:
sortedUsers = sortedUsers.OrderBy(u => u.Username);
break;
}
if (Filter.DisplayStyleControl.Dropdown.Current.Value == SortDirection.Descending)
sortedUsers = sortedUsers.Reverse();
2020-03-04 11:58:15 +00:00
var newPanels = new FillFlowContainer<UserPanel>
2018-04-13 09:19:50 +00:00
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(10f),
Margin = new MarginPadding { Top = 10 },
2019-12-18 17:02:57 +00:00
ChildrenEnumerable = sortedUsers.Select(u =>
2018-04-13 09:19:50 +00:00
{
2020-03-04 11:58:15 +00:00
UserPanel panel;
2019-04-01 03:16:05 +00:00
2019-12-18 17:02:57 +00:00
switch (Filter.DisplayStyleControl.DisplayStyle.Value)
2018-04-13 09:19:50 +00:00
{
case PanelDisplayStyle.Grid:
2020-03-04 11:58:15 +00:00
panel = new UserGridPanel(u)
2018-04-13 09:19:50 +00:00
{
Anchor = Anchor.TopCentre,
2020-03-04 11:58:15 +00:00
Origin = Anchor.TopCentre,
Width = 290,
2018-04-13 09:19:50 +00:00
};
break;
2019-04-01 03:16:05 +00:00
2018-04-13 09:19:50 +00:00
default:
2020-03-04 11:58:15 +00:00
panel = new UserListPanel(u);
2018-04-13 09:19:50 +00:00
break;
}
2019-02-28 04:31:40 +00:00
2018-04-13 09:19:50 +00:00
panel.Status.BindTo(u.Status);
panel.Activity.BindTo(u.Activity);
2018-04-13 09:19:50 +00:00
return panel;
})
};
LoadComponentAsync(newPanels, f =>
{
if (panels != null)
ScrollFlow.Remove(panels);
2019-08-27 00:53:16 +00:00
loading.Hide();
2018-04-13 09:19:50 +00:00
ScrollFlow.Add(panels = newPanels);
}, (loadCancellation = new CancellationTokenSource()).Token);
2018-04-13 09:19:50 +00:00
}
private void onFilterUpdate()
{
if (Filter.Tabs.Current.Value == SocialSortCriteria.Rank)
{
queueUpdate();
return;
}
2019-12-18 17:02:57 +00:00
recreatePanels();
2018-04-13 09:19:50 +00:00
}
private void clearPanels()
{
loading.Show();
loadCancellation?.Cancel();
2018-04-13 09:19:50 +00:00
if (panels != null)
{
panels.Expire();
panels = null;
}
}
2019-05-14 05:18:06 +00:00
public override void APIStateChanged(IAPIProvider api, APIState state)
2018-04-13 09:19:50 +00:00
{
switch (state)
{
case APIState.Online:
queueUpdate();
2018-04-13 09:19:50 +00:00
break;
2019-04-01 03:16:05 +00:00
2018-04-13 09:19:50 +00:00
default:
Users = null;
clearPanels();
break;
}
}
}
}