1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-14 01:42:59 +08:00

Merge pull request #16626 from peppy/fix-skin-section-realm-usage

Refactor `SkinSection` to avoid unnecessary realm queries
This commit is contained in:
Dan Balasescu 2022-01-26 19:01:15 +09:00 committed by GitHub
commit b1a23486c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 48 deletions

View File

@ -216,12 +216,6 @@ namespace osu.Game.Database
return new RealmLiveUnmanaged<T>(realmObject);
}
public static List<Live<T>> ToLive<T>(this IEnumerable<T> realmList, RealmAccess realm)
where T : RealmObject, IHasGuidPrimaryKey
{
return realmList.Select(l => new RealmLive<T>(l, realm)).Cast<Live<T>>().ToList();
}
public static Live<T> ToLive<T>(this T realmObject, RealmAccess realm)
where T : RealmObject, IHasGuidPrimaryKey
{

View File

@ -18,6 +18,7 @@ using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
using osu.Game.Skinning;
using osu.Game.Skinning.Editor;
using Realms;
namespace osu.Game.Overlays.Settings.Sections
{
@ -41,7 +42,7 @@ namespace osu.Game.Overlays.Settings.Sections
Name = "<Random Skin>",
}.ToLiveUnmanaged();
private List<Live<SkinInfo>> skinItems;
private readonly List<Live<SkinInfo>> dropdownItems = new List<Live<SkinInfo>>();
[Resolved]
private SkinManager skins { get; set; }
@ -51,12 +52,6 @@ namespace osu.Game.Overlays.Settings.Sections
private IDisposable realmSubscription;
private IQueryable<SkinInfo> queryRealmSkins() =>
realm.Realm.All<SkinInfo>()
.Where(s => !s.DeletePending)
.OrderByDescending(s => s.Protected) // protected skins should be at the top.
.ThenBy(s => s.Name, StringComparer.OrdinalIgnoreCase);
[BackgroundDependencyLoader(permitNulls: true)]
private void load(OsuConfigManager config, [CanBeNull] SkinEditorOverlay skinEditor)
{
@ -83,20 +78,21 @@ namespace osu.Game.Overlays.Settings.Sections
skinDropdown.Current = dropdownBindable;
realmSubscription = realm.RegisterForNotifications(r => queryRealmSkins(), (sender, changes, error) =>
{
// The first fire of this is a bit redundant due to the call below,
// but this is safest in case the subscription is restored after a context recycle.
updateItems();
});
updateItems();
realmSubscription = realm.RegisterForNotifications(r => realm.Realm.All<SkinInfo>()
.Where(s => !s.DeletePending)
.OrderByDescending(s => s.Protected) // protected skins should be at the top.
.ThenBy(s => s.Name, StringComparer.OrdinalIgnoreCase), skinsChanged);
configBindable.BindValueChanged(id => Scheduler.AddOnce(updateSelectedSkinFromConfig));
updateSelectedSkinFromConfig();
dropdownBindable.BindValueChanged(skin =>
dropdownBindable.BindValueChanged(dropdownSelectionChanged);
}
private void dropdownSelectionChanged(ValueChangedEvent<Live<SkinInfo>> skin)
{
// Only handle cases where it's clear the user has intent to change skins.
if (skin.OldValue == null) return;
if (skin.NewValue.Equals(random_skin_info))
{
var skinBefore = skins.CurrentSkinInfo.Value;
@ -113,7 +109,27 @@ namespace osu.Game.Overlays.Settings.Sections
}
configBindable.Value = skin.NewValue.ID.ToString();
});
}
private void skinsChanged(IRealmCollection<SkinInfo> sender, ChangeSet changes, Exception error)
{
// This can only mean that realm is recycling, else we would see the protected skins.
// Because we are using `Live<>` in this class, we don't need to worry about this scenario too much.
if (!sender.Any())
return;
int protectedCount = sender.Count(s => s.Protected);
// For simplicity repopulate the full list.
// In the future we should change this to properly handle ChangeSet events.
dropdownItems.Clear();
foreach (var skin in sender)
dropdownItems.Add(skin.ToLive(realm));
dropdownItems.Insert(protectedCount, random_skin_info);
skinDropdown.Items = dropdownItems;
updateSelectedSkinFromConfig();
}
private void updateSelectedSkinFromConfig()
@ -126,17 +142,6 @@ namespace osu.Game.Overlays.Settings.Sections
dropdownBindable.Value = skin ?? skinDropdown.Items.First();
}
private void updateItems()
{
int protectedCount = queryRealmSkins().Count(s => s.Protected);
skinItems = queryRealmSkins().ToLive(realm);
skinItems.Insert(protectedCount, random_skin_info);
skinDropdown.Items = skinItems;
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);