mirror of
https://github.com/osukey/osukey.git
synced 2025-07-02 08:49:59 +09:00
Update all read queries to use direct realm subscriptions/queries
This commit is contained in:
@ -37,18 +37,20 @@ namespace osu.Game.Tests.Database
|
||||
[Test]
|
||||
public void TestDefaultsPopulationAndQuery()
|
||||
{
|
||||
Assert.That(keyBindingStore.Query().Count, Is.EqualTo(0));
|
||||
Assert.That(query().Count, Is.EqualTo(0));
|
||||
|
||||
KeyBindingContainer testContainer = new TestKeyBindingContainer();
|
||||
|
||||
keyBindingStore.Register(testContainer);
|
||||
|
||||
Assert.That(keyBindingStore.Query().Count, Is.EqualTo(3));
|
||||
Assert.That(query().Count, Is.EqualTo(3));
|
||||
|
||||
Assert.That(keyBindingStore.Query(GlobalAction.Back).Count, Is.EqualTo(1));
|
||||
Assert.That(keyBindingStore.Query(GlobalAction.Select).Count, Is.EqualTo(2));
|
||||
Assert.That(query().Where(k => k.Action == (int)GlobalAction.Back).Count, Is.EqualTo(1));
|
||||
Assert.That(query().Where(k => k.Action == (int)GlobalAction.Select).Count, Is.EqualTo(2));
|
||||
}
|
||||
|
||||
private IQueryable<RealmKeyBinding> query() => realmContextFactory.Get().All<RealmKeyBinding>();
|
||||
|
||||
[Test]
|
||||
public void TestUpdateViaQueriedReference()
|
||||
{
|
||||
@ -56,7 +58,7 @@ namespace osu.Game.Tests.Database
|
||||
|
||||
keyBindingStore.Register(testContainer);
|
||||
|
||||
var backBinding = keyBindingStore.Query(GlobalAction.Back).Single();
|
||||
var backBinding = query().Single(k => k.Action == (int)GlobalAction.Back);
|
||||
|
||||
Assert.That(((IKeyBinding)backBinding).KeyCombination.Keys, Is.EquivalentTo(new[] { InputKey.Escape }));
|
||||
|
||||
@ -65,7 +67,7 @@ namespace osu.Game.Tests.Database
|
||||
Assert.That(((IKeyBinding)backBinding).KeyCombination.Keys, Is.EquivalentTo(new[] { InputKey.BackSpace }));
|
||||
|
||||
// check still correct after re-query.
|
||||
backBinding = keyBindingStore.Query(GlobalAction.Back).Single();
|
||||
backBinding = query().Single(k => k.Action == (int)GlobalAction.Back);
|
||||
Assert.That(((IKeyBinding)backBinding).KeyCombination.Keys, Is.EquivalentTo(new[] { InputKey.BackSpace }));
|
||||
}
|
||||
|
||||
|
@ -11,11 +11,11 @@ namespace osu.Game.Database
|
||||
{
|
||||
protected readonly Storage? Storage;
|
||||
|
||||
protected readonly IRealmFactory ContextFactory;
|
||||
protected readonly IRealmFactory RealmFactory;
|
||||
|
||||
protected RealmBackedStore(IRealmFactory contextFactory, Storage? storage = null)
|
||||
protected RealmBackedStore(IRealmFactory realmFactory, Storage? storage = null)
|
||||
{
|
||||
ContextFactory = contextFactory;
|
||||
RealmFactory = realmFactory;
|
||||
Storage = storage;
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ namespace osu.Game.Database
|
||||
|
||||
try
|
||||
{
|
||||
context = getContextForCurrentThread();
|
||||
context = createContext();
|
||||
|
||||
currentWriteTransaction ??= context.BeginWrite();
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Rulesets;
|
||||
using Realms;
|
||||
|
||||
namespace osu.Game.Input.Bindings
|
||||
{
|
||||
@ -22,6 +23,9 @@ namespace osu.Game.Input.Bindings
|
||||
|
||||
private readonly int? variant;
|
||||
|
||||
private IDisposable realmSubscription;
|
||||
private IQueryable<RealmKeyBinding> realmKeyBindings;
|
||||
|
||||
[Resolved]
|
||||
private RealmKeyBindingStore store { get; set; }
|
||||
|
||||
@ -49,35 +53,42 @@ namespace osu.Game.Input.Bindings
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
var realm = realmFactory.Get();
|
||||
|
||||
if (ruleset == null || ruleset.ID.HasValue)
|
||||
{
|
||||
var rulesetId = ruleset?.ID;
|
||||
|
||||
realmKeyBindings = realm.All<RealmKeyBinding>()
|
||||
.Where(b => b.RulesetID == rulesetId && b.Variant == variant);
|
||||
|
||||
realmSubscription = realmKeyBindings
|
||||
.SubscribeForNotifications((sender, changes, error) =>
|
||||
{
|
||||
// first subscription ignored as we are handling this in LoadComplete.
|
||||
if (changes == null)
|
||||
return;
|
||||
|
||||
ReloadMappings();
|
||||
});
|
||||
}
|
||||
|
||||
base.LoadComplete();
|
||||
store.KeyBindingChanged += ReloadMappings;
|
||||
}
|
||||
|
||||
protected override void ReloadMappings()
|
||||
{
|
||||
if (realmKeyBindings != null)
|
||||
KeyBindings = realmKeyBindings.Detach();
|
||||
else
|
||||
base.ReloadMappings();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (store != null)
|
||||
store.KeyBindingChanged -= ReloadMappings;
|
||||
}
|
||||
|
||||
protected override void ReloadMappings()
|
||||
{
|
||||
if (ruleset != null && !ruleset.ID.HasValue)
|
||||
// if the provided ruleset is not stored to the database, we have no way to retrieve custom bindings.
|
||||
// fallback to defaults instead.
|
||||
KeyBindings = DefaultKeyBindings;
|
||||
else
|
||||
{
|
||||
var rulesetId = ruleset?.ID;
|
||||
|
||||
// #1
|
||||
KeyBindings = store.Query(rulesetId, variant).Detach();
|
||||
|
||||
// #2 (Clearly shows lifetime of realm context access)
|
||||
using (var realm = realmFactory.Get())
|
||||
KeyBindings = realm.All<RealmKeyBinding>().Where(b => b.RulesetID == rulesetId && b.Variant == variant).Detach();
|
||||
}
|
||||
realmSubscription?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ namespace osu.Game.Input
|
||||
/// </summary>
|
||||
public event Action? KeyBindingChanged;
|
||||
|
||||
public RealmKeyBindingStore(RealmContextFactory contextFactory, Storage? storage = null)
|
||||
: base(contextFactory, storage)
|
||||
public RealmKeyBindingStore(RealmContextFactory realmFactory, Storage? storage = null)
|
||||
: base(realmFactory, storage)
|
||||
{
|
||||
}
|
||||
|
||||
@ -57,35 +57,13 @@ namespace osu.Game.Input
|
||||
{
|
||||
var instance = ruleset.CreateInstance();
|
||||
|
||||
using (ContextFactory.GetForWrite())
|
||||
using (RealmFactory.GetForWrite())
|
||||
{
|
||||
foreach (var variant in instance.AvailableVariants)
|
||||
insertDefaults(instance.GetDefaultKeyBindings(variant), ruleset.ID, variant);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve all key bindings for the provided specification.
|
||||
/// </summary>
|
||||
/// <param name="rulesetId">An optional ruleset ID. If null, global bindings are returned.</param>
|
||||
/// <param name="variant">An optional ruleset variant. If null, the no-variant bindings are returned.</param>
|
||||
/// <returns>A list of all key bindings found for the query, detached from the database.</returns>
|
||||
public List<RealmKeyBinding> Query(int? rulesetId = null, int? variant = null) => query(rulesetId, variant).ToList();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve all key bindings for the provided action type.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to lookup.</param>
|
||||
/// <typeparam name="T">The enum type of the action.</typeparam>
|
||||
/// <returns>A list of all key bindings found for the query, detached from the database.</returns>
|
||||
public List<RealmKeyBinding> Query<T>(T action)
|
||||
where T : Enum
|
||||
{
|
||||
int lookup = (int)(object)action;
|
||||
|
||||
return query(null, null).Where(rkb => rkb.Action == lookup).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the database mapping for the provided key binding.
|
||||
/// </summary>
|
||||
@ -96,7 +74,7 @@ namespace osu.Game.Input
|
||||
// the incoming instance could already be a live access object.
|
||||
Live<RealmKeyBinding>? realmBinding = keyBinding as Live<RealmKeyBinding>;
|
||||
|
||||
using (var realm = ContextFactory.GetForWrite())
|
||||
using (var realm = RealmFactory.GetForWrite())
|
||||
{
|
||||
if (realmBinding == null)
|
||||
{
|
||||
@ -105,7 +83,7 @@ namespace osu.Game.Input
|
||||
// if neither of the above cases succeeded, retrieve a realm object for further processing.
|
||||
rkb = realm.Context.Find<RealmKeyBinding>(keyBinding.ID);
|
||||
|
||||
realmBinding = new Live<RealmKeyBinding>(rkb, ContextFactory);
|
||||
realmBinding = new Live<RealmKeyBinding>(rkb, RealmFactory);
|
||||
}
|
||||
|
||||
realmBinding.PerformUpdate(modification);
|
||||
@ -116,7 +94,7 @@ namespace osu.Game.Input
|
||||
|
||||
private void insertDefaults(IEnumerable<IKeyBinding> defaults, int? rulesetId = null, int? variant = null)
|
||||
{
|
||||
using (var usage = ContextFactory.GetForWrite())
|
||||
using (var usage = RealmFactory.GetForWrite())
|
||||
{
|
||||
// compare counts in database vs defaults
|
||||
foreach (var group in defaults.GroupBy(k => k.Action))
|
||||
@ -149,6 +127,6 @@ namespace osu.Game.Input
|
||||
/// <param name="rulesetId">An optional ruleset ID. If null, global bindings are returned.</param>
|
||||
/// <param name="variant">An optional ruleset variant. If null, the no-variant bindings are returned.</param>
|
||||
private IQueryable<RealmKeyBinding> query(int? rulesetId = null, int? variant = null) =>
|
||||
ContextFactory.Get().All<RealmKeyBinding>().Where(b => b.RulesetID == rulesetId && b.Variant == variant);
|
||||
RealmFactory.Get().All<RealmKeyBinding>().Where(b => b.RulesetID == rulesetId && b.Variant == variant);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets;
|
||||
using osuTK;
|
||||
@ -33,20 +33,25 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RealmKeyBindingStore store)
|
||||
private void load(RealmContextFactory realmFactory)
|
||||
{
|
||||
var bindings = store.Query(Ruleset?.ID, variant).Detach();
|
||||
var rulesetId = Ruleset?.ID;
|
||||
|
||||
foreach (var defaultGroup in Defaults.GroupBy(d => d.Action))
|
||||
using (var realm = realmFactory.Get())
|
||||
{
|
||||
int intKey = (int)defaultGroup.Key;
|
||||
var bindings = realm.All<RealmKeyBinding>().Where(b => b.RulesetID == rulesetId && b.Variant == variant).Detach();
|
||||
|
||||
// one row per valid action.
|
||||
Add(new KeyBindingRow(defaultGroup.Key, bindings.Where(b => b.Action.Equals(intKey)))
|
||||
foreach (var defaultGroup in Defaults.GroupBy(d => d.Action))
|
||||
{
|
||||
AllowMainMouseButtons = Ruleset != null,
|
||||
Defaults = defaultGroup.Select(d => d.KeyCombination)
|
||||
});
|
||||
int intKey = (int)defaultGroup.Key;
|
||||
|
||||
// one row per valid action.
|
||||
Add(new KeyBindingRow(defaultGroup.Key, bindings.Where(b => b.Action.Equals(intKey)))
|
||||
{
|
||||
AllowMainMouseButtons = Ruleset != null,
|
||||
Defaults = defaultGroup.Select(d => d.KeyCombination)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Add(new ResetButton
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Caching;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -13,12 +12,12 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
@ -75,7 +74,7 @@ namespace osu.Game.Overlays.Toolbar
|
||||
protected FillFlowContainer Flow;
|
||||
|
||||
[Resolved]
|
||||
private RealmKeyBindingStore keyBindings { get; set; }
|
||||
private RealmContextFactory realmFactory { get; set; }
|
||||
|
||||
protected ToolbarButton()
|
||||
: base(HoverSampleSet.Loud)
|
||||
@ -158,32 +157,28 @@ namespace osu.Game.Overlays.Toolbar
|
||||
};
|
||||
}
|
||||
|
||||
private readonly Cached tooltipKeyBinding = new Cached();
|
||||
private RealmKeyBinding realmKeyBinding;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
keyBindings.KeyBindingChanged += () => tooltipKeyBinding.Invalidate();
|
||||
updateKeyBindingTooltip();
|
||||
}
|
||||
|
||||
private void updateKeyBindingTooltip()
|
||||
{
|
||||
if (tooltipKeyBinding.IsValid)
|
||||
return;
|
||||
|
||||
keyBindingTooltip.Text = string.Empty;
|
||||
base.LoadComplete();
|
||||
|
||||
if (Hotkey != null)
|
||||
{
|
||||
KeyCombination? binding = keyBindings.Query(Hotkey.Value).FirstOrDefault()?.KeyCombination;
|
||||
var keyBindingString = binding?.ReadableString();
|
||||
var realm = realmFactory.Get();
|
||||
realmKeyBinding = realm.All<RealmKeyBinding>().FirstOrDefault(rkb => rkb.RulesetID == null && rkb.Action == (int)Hotkey.Value);
|
||||
|
||||
if (!string.IsNullOrEmpty(keyBindingString))
|
||||
keyBindingTooltip.Text = $" ({keyBindingString})";
|
||||
if (realmKeyBinding != null)
|
||||
{
|
||||
realmKeyBinding.PropertyChanged += (sender, args) =>
|
||||
{
|
||||
if (args.PropertyName == nameof(realmKeyBinding.KeyCombination))
|
||||
updateKeyBindingTooltip();
|
||||
};
|
||||
}
|
||||
|
||||
updateKeyBindingTooltip();
|
||||
}
|
||||
|
||||
tooltipKeyBinding.Validate();
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e) => true;
|
||||
@ -224,6 +219,19 @@ namespace osu.Game.Overlays.Toolbar
|
||||
public void OnReleased(GlobalAction action)
|
||||
{
|
||||
}
|
||||
|
||||
private void updateKeyBindingTooltip()
|
||||
{
|
||||
if (realmKeyBinding != null)
|
||||
{
|
||||
KeyCombination? binding = ((IKeyBinding)realmKeyBinding).KeyCombination;
|
||||
|
||||
var keyBindingString = binding?.ReadableString();
|
||||
|
||||
if (!string.IsNullOrEmpty(keyBindingString))
|
||||
keyBindingTooltip.Text = $" ({keyBindingString})";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class OpaqueBackground : Container
|
||||
|
Reference in New Issue
Block a user