mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 05:32:54 +08:00
Make Room.RecentParticipants
non-bindable
This commit is contained in:
parent
dc5337d771
commit
b16edbbf52
@ -199,11 +199,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
if (room.RecentParticipants.Count == 0)
|
||||
{
|
||||
room.RecentParticipants.AddRange(Enumerable.Range(0, 20).Select(i => new APIUser
|
||||
room.RecentParticipants = Enumerable.Range(0, 20).Select(i => new APIUser
|
||||
{
|
||||
Id = i,
|
||||
Username = $"User {i}"
|
||||
}));
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
return new DrawableLoungeRoom(room)
|
||||
|
@ -138,17 +138,17 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
private void addUser(int id)
|
||||
{
|
||||
SelectedRoom.Value.RecentParticipants.Add(new APIUser
|
||||
SelectedRoom.Value.RecentParticipants = SelectedRoom.Value.RecentParticipants.Append(new APIUser
|
||||
{
|
||||
Id = id,
|
||||
Username = $"User {id}"
|
||||
});
|
||||
}).ToArray();
|
||||
SelectedRoom.Value.ParticipantCount++;
|
||||
}
|
||||
|
||||
private void removeUserAt(int index)
|
||||
{
|
||||
SelectedRoom.Value.RecentParticipants.RemoveAt(index);
|
||||
SelectedRoom.Value.RecentParticipants = SelectedRoom.Value.RecentParticipants.Where(u => !u.Equals(SelectedRoom.Value.RecentParticipants[index])).ToArray();
|
||||
SelectedRoom.Value.ParticipantCount--;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
@ -19,17 +20,16 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
|
||||
AddStep("create list", () =>
|
||||
{
|
||||
SelectedRoom.Value = new Room { RoomID = 7 };
|
||||
|
||||
for (int i = 0; i < 50; i++)
|
||||
SelectedRoom.Value = new Room
|
||||
{
|
||||
SelectedRoom.Value.RecentParticipants.Add(new APIUser
|
||||
RoomID = 7,
|
||||
RecentParticipants = Enumerable.Range(0, 50).Select(_ => new APIUser
|
||||
{
|
||||
Username = "peppy",
|
||||
Statistics = new UserStatistics { GlobalRank = 1234 },
|
||||
Id = 2
|
||||
});
|
||||
}
|
||||
}).ToArray()
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
{
|
||||
room.Name = "my awesome room";
|
||||
room.Host = API.LocalUser.Value;
|
||||
room.RecentParticipants.Add(room.Host);
|
||||
room.RecentParticipants = [room.Host];
|
||||
room.EndDate = DateTimeOffset.Now.AddMinutes(5);
|
||||
room.Playlist.Add(new PlaylistItem(importedBeatmap.Beatmaps.First())
|
||||
{
|
||||
@ -86,7 +86,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
room.Name = "my awesome room";
|
||||
room.MaxAttempts = 5;
|
||||
room.Host = API.LocalUser.Value;
|
||||
room.RecentParticipants.Add(room.Host);
|
||||
room.RecentParticipants = [room.Host];
|
||||
room.EndDate = DateTimeOffset.Now.AddMinutes(5);
|
||||
room.Playlist.Add(new PlaylistItem(importedBeatmap.Beatmaps.First())
|
||||
{
|
||||
|
@ -487,11 +487,11 @@ namespace osu.Game.Online.Multiplayer
|
||||
{
|
||||
Debug.Assert(APIRoom != null);
|
||||
|
||||
APIRoom.RecentParticipants.Add(user.User ?? new APIUser
|
||||
APIRoom.RecentParticipants = APIRoom.RecentParticipants.Append(user.User ?? new APIUser
|
||||
{
|
||||
Id = user.UserID,
|
||||
Username = "[Unresolved]"
|
||||
});
|
||||
}).ToArray();
|
||||
APIRoom.ParticipantCount++;
|
||||
}
|
||||
|
||||
@ -506,7 +506,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
PlayingUserIds.Remove(user.UserID);
|
||||
|
||||
Debug.Assert(APIRoom != null);
|
||||
APIRoom.RecentParticipants.RemoveAll(u => u.Id == user.UserID);
|
||||
APIRoom.RecentParticipants = APIRoom.RecentParticipants.Where(u => u.Id != user.UserID).ToArray();
|
||||
APIRoom.ParticipantCount--;
|
||||
|
||||
callback?.Invoke(user);
|
||||
|
@ -137,6 +137,15 @@ namespace osu.Game.Online.Rooms
|
||||
set => SetField(ref participantCount, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The set of most recent participants in the room.
|
||||
/// </summary>
|
||||
public IReadOnlyList<APIUser> RecentParticipants
|
||||
{
|
||||
get => recentParticipants;
|
||||
set => SetList(ref recentParticipants, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The match type.
|
||||
/// </summary>
|
||||
@ -282,6 +291,9 @@ namespace osu.Game.Online.Rooms
|
||||
[JsonProperty("participant_count")]
|
||||
private int participantCount;
|
||||
|
||||
[JsonProperty("recent_participants")]
|
||||
private IReadOnlyList<APIUser> recentParticipants = [];
|
||||
|
||||
[JsonProperty("max_attempts", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
private int? maxAttempts;
|
||||
|
||||
@ -324,10 +336,6 @@ namespace osu.Game.Online.Rooms
|
||||
[JsonProperty("playlist")]
|
||||
public readonly BindableList<PlaylistItem> Playlist = new BindableList<PlaylistItem>();
|
||||
|
||||
[Cached]
|
||||
[JsonProperty("recent_participants")]
|
||||
public readonly BindableList<APIUser> RecentParticipants = new BindableList<APIUser>();
|
||||
|
||||
/// <summary>
|
||||
/// Copies values from another <see cref="Room"/> into this one.
|
||||
/// </summary>
|
||||
@ -369,11 +377,7 @@ namespace osu.Game.Online.Rooms
|
||||
Playlist.AddRange(other.Playlist);
|
||||
}
|
||||
|
||||
if (!RecentParticipants.SequenceEqual(other.RecentParticipants))
|
||||
{
|
||||
RecentParticipants.Clear();
|
||||
RecentParticipants.AddRange(other.RecentParticipants);
|
||||
}
|
||||
RecentParticipants = other.RecentParticipants;
|
||||
}
|
||||
|
||||
public void RemoveExpiredPlaylistItems()
|
||||
@ -411,6 +415,16 @@ namespace osu.Game.Online.Rooms
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null!)
|
||||
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
|
||||
protected bool SetList<T>(ref IReadOnlyList<T> list, IReadOnlyList<T> value, [CallerMemberName] string propertyName = null!)
|
||||
{
|
||||
if (list.SequenceEqual(value))
|
||||
return false;
|
||||
|
||||
list = value;
|
||||
OnPropertyChanged(propertyName);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null!)
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(field, value))
|
||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
|
||||
AddInternal(scroll = new OsuScrollContainer(direction)
|
||||
{
|
||||
Child = list = new ParticipantsList()
|
||||
Child = list = new ParticipantsList(room)
|
||||
});
|
||||
|
||||
switch (direction)
|
||||
|
@ -1,15 +1,14 @@
|
||||
// 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.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using System.ComponentModel;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Users.Drawables;
|
||||
using osuTK;
|
||||
|
||||
@ -57,15 +56,29 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
}
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private readonly Room room;
|
||||
|
||||
public ParticipantsList(Room room)
|
||||
{
|
||||
RecentParticipants.CollectionChanged += (_, _) => updateParticipants();
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
room.PropertyChanged += onRoomPropertyChanged;
|
||||
updateParticipants();
|
||||
}
|
||||
|
||||
private ScheduledDelegate scheduledUpdate;
|
||||
private FillFlowContainer<UserTile> tiles;
|
||||
private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(Room.RecentParticipants))
|
||||
updateParticipants();
|
||||
}
|
||||
|
||||
private ScheduledDelegate? scheduledUpdate;
|
||||
private FillFlowContainer<UserTile>? tiles;
|
||||
|
||||
private void updateParticipants()
|
||||
{
|
||||
@ -83,8 +96,8 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
Spacing = Vector2.One
|
||||
};
|
||||
|
||||
for (int i = 0; i < RecentParticipants.Count; i++)
|
||||
tiles.Add(new UserTile { User = RecentParticipants[i] });
|
||||
for (int i = 0; i < room.RecentParticipants.Count; i++)
|
||||
tiles.Add(new UserTile { User = room.RecentParticipants[i] });
|
||||
|
||||
AddInternal(tiles);
|
||||
|
||||
@ -92,9 +105,15 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
room.PropertyChanged -= onRoomPropertyChanged;
|
||||
}
|
||||
|
||||
private partial class UserTile : CompositeDrawable
|
||||
{
|
||||
public APIUser User
|
||||
public APIUser? User
|
||||
{
|
||||
get => avatar.User;
|
||||
set => avatar.User = value;
|
||||
|
@ -1,9 +1,8 @@
|
||||
// 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.
|
||||
|
||||
using System.Collections.Specialized;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
@ -165,12 +164,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
RecentParticipants.BindCollectionChanged(onParticipantsChanged, true);
|
||||
|
||||
room.PropertyChanged += onRoomPropertyChanged;
|
||||
|
||||
updateRoomHost();
|
||||
updateRoomParticipantCount();
|
||||
updateRoomParticipants();
|
||||
}
|
||||
|
||||
private int numberOfCircles = 4;
|
||||
@ -190,43 +188,38 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
||||
|
||||
// Reinitialising the list looks janky, but this is unlikely to be used in a setting where it's visible.
|
||||
clearUsers();
|
||||
foreach (var u in RecentParticipants)
|
||||
foreach (var u in room.RecentParticipants)
|
||||
addUser(u);
|
||||
|
||||
updateHiddenUsers();
|
||||
}
|
||||
}
|
||||
|
||||
private void onParticipantsChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
private void updateRoomParticipants()
|
||||
{
|
||||
switch (e.Action)
|
||||
HashSet<APIUser> newUsers = room.RecentParticipants.ToHashSet();
|
||||
|
||||
avatarFlow.RemoveAll(a =>
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
Debug.Assert(e.NewItems != null);
|
||||
// Avatar with no user. Really shouldn't ever be the case but asserting it correctly is difficult.
|
||||
if (a.User == null)
|
||||
return false;
|
||||
|
||||
foreach (var added in e.NewItems.OfType<APIUser>())
|
||||
addUser(added);
|
||||
break;
|
||||
// User was previously and still is a participant. Keep them around but remove them from the new set.
|
||||
// This will be useful when we add all remaining users (now just the new participants) to the flow.
|
||||
if (newUsers.Contains(a.User))
|
||||
{
|
||||
newUsers.Remove(a.User);
|
||||
return false;
|
||||
}
|
||||
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
Debug.Assert(e.OldItems != null);
|
||||
// User is no longer a participant. Remove them from the flow.
|
||||
return true;
|
||||
}, true);
|
||||
|
||||
foreach (var removed in e.OldItems.OfType<APIUser>())
|
||||
removeUser(removed);
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Reset:
|
||||
clearUsers();
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Replace:
|
||||
case NotifyCollectionChangedAction.Move:
|
||||
// Easiest is to just reinitialise the whole list. These are unlikely to ever be use cases.
|
||||
clearUsers();
|
||||
foreach (var u in RecentParticipants)
|
||||
addUser(u);
|
||||
break;
|
||||
}
|
||||
// Add all remaining users to the flow.
|
||||
foreach (var u in newUsers)
|
||||
addUser(u);
|
||||
|
||||
updateHiddenUsers();
|
||||
}
|
||||
@ -239,11 +232,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
||||
avatarFlow.Add(new CircularAvatar { User = user });
|
||||
}
|
||||
|
||||
private void removeUser(APIUser user)
|
||||
{
|
||||
avatarFlow.RemoveAll(a => a.User == user, true);
|
||||
}
|
||||
|
||||
private void clearUsers()
|
||||
{
|
||||
avatarFlow.Clear();
|
||||
@ -253,7 +241,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
||||
private void updateHiddenUsers()
|
||||
{
|
||||
int hiddenCount = 0;
|
||||
if (RecentParticipants.Count > NumberOfCircles)
|
||||
if (room.RecentParticipants.Count > NumberOfCircles)
|
||||
hiddenCount = room.ParticipantCount - NumberOfCircles + 1;
|
||||
|
||||
hiddenUsers.Count = hiddenCount;
|
||||
@ -262,7 +250,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
||||
avatarFlow.Remove(avatarFlow.Last(), true);
|
||||
else if (displayedCircles < NumberOfCircles)
|
||||
{
|
||||
var nextUser = RecentParticipants.FirstOrDefault(u => avatarFlow.All(a => a.User != u));
|
||||
var nextUser = room.RecentParticipants.FirstOrDefault(u => avatarFlow.All(a => a.User != u));
|
||||
if (nextUser != null) addUser(nextUser);
|
||||
}
|
||||
}
|
||||
@ -278,6 +266,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
|
||||
case nameof(Room.ParticipantCount):
|
||||
updateRoomParticipantCount();
|
||||
break;
|
||||
|
||||
case nameof(Room.RecentParticipants):
|
||||
updateRoomParticipants();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Rooms;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay
|
||||
@ -16,8 +15,5 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
{
|
||||
[Resolved(typeof(Room))]
|
||||
protected BindableList<PlaylistItem> Playlist { get; private set; } = null!;
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected BindableList<APIUser> RecentParticipants { get; private set; } = null!;
|
||||
}
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
responseRoom.Password = responseRoom.HasPassword ? Guid.NewGuid().ToString() : null;
|
||||
|
||||
if (!withParticipants)
|
||||
responseRoom.RecentParticipants.Clear();
|
||||
responseRoom.RecentParticipants = [];
|
||||
|
||||
return responseRoom;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user