mirror of
https://github.com/osukey/osukey.git
synced 2025-06-09 05:19:11 +09:00
Merge pull request #16544 from peppy/realm-migration-ui
Show realm migration progress via a simple UI
This commit is contained in:
commit
1a1f9d9bec
@ -5,7 +5,6 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.EntityFrameworkCore.Storage;
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
using osu.Framework.Development;
|
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Statistics;
|
using osu.Framework.Statistics;
|
||||||
@ -151,9 +150,6 @@ namespace osu.Game.Database
|
|||||||
{
|
{
|
||||||
Logger.Log($"Creating full EF database backup at {backupFilename}", LoggingTarget.Database);
|
Logger.Log($"Creating full EF database backup at {backupFilename}", LoggingTarget.Database);
|
||||||
|
|
||||||
if (DebugUtils.IsDebugBuild)
|
|
||||||
Logger.Log("Your development database has been fully migrated to realm. If you switch back to a pre-realm branch and need your previous database, rename the backup file back to \"client.db\".\n\nNote that doing this can potentially leave your file store in a bad state.", level: LogLevel.Important);
|
|
||||||
|
|
||||||
using (var source = storage.GetStream(DATABASE_NAME))
|
using (var source = storage.GetStream(DATABASE_NAME))
|
||||||
using (var destination = storage.GetStream(backupFilename, FileAccess.Write, FileMode.CreateNew))
|
using (var destination = storage.GetStream(backupFilename, FileAccess.Write, FileMode.CreateNew))
|
||||||
source.CopyTo(destination);
|
source.CopyTo(destination);
|
||||||
|
@ -1,43 +1,102 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Development;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Platform;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Models;
|
using osu.Game.Models;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
using Realms;
|
using Realms;
|
||||||
|
|
||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
namespace osu.Game.Database
|
namespace osu.Game.Database
|
||||||
{
|
{
|
||||||
internal class EFToRealmMigrator
|
internal class EFToRealmMigrator : CompositeDrawable
|
||||||
{
|
{
|
||||||
private readonly DatabaseContextFactory efContextFactory;
|
public bool FinishedMigrating { get; private set; }
|
||||||
private readonly RealmContextFactory realmContextFactory;
|
|
||||||
private readonly OsuConfigManager config;
|
|
||||||
private readonly Storage storage;
|
|
||||||
|
|
||||||
public EFToRealmMigrator(DatabaseContextFactory efContextFactory, RealmContextFactory realmContextFactory, OsuConfigManager config, Storage storage)
|
[Resolved]
|
||||||
|
private DatabaseContextFactory efContextFactory { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private RealmContextFactory realmContextFactory { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuConfigManager config { get; set; } = null!;
|
||||||
|
|
||||||
|
private readonly OsuSpriteText currentOperationText;
|
||||||
|
|
||||||
|
public EFToRealmMigrator()
|
||||||
{
|
{
|
||||||
this.efContextFactory = efContextFactory;
|
RelativeSizeAxes = Axes.Both;
|
||||||
this.realmContextFactory = realmContextFactory;
|
|
||||||
this.config = config;
|
InternalChildren = new Drawable[]
|
||||||
this.storage = storage;
|
{
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Spacing = new Vector2(10),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Text = "Database migration in progress",
|
||||||
|
Font = OsuFont.Default.With(size: 40)
|
||||||
|
},
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Text = "This could take a few minutes depending on the speed of your disk(s).",
|
||||||
|
Font = OsuFont.Default.With(size: 30)
|
||||||
|
},
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Text = "Please keep the window open until this completes!",
|
||||||
|
Font = OsuFont.Default.With(size: 30)
|
||||||
|
},
|
||||||
|
new LoadingSpinner(true)
|
||||||
|
{
|
||||||
|
State = { Value = Visibility.Visible }
|
||||||
|
},
|
||||||
|
currentOperationText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Font = OsuFont.Default.With(size: 30)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
createBackup();
|
base.LoadComplete();
|
||||||
|
|
||||||
|
Task.Factory.StartNew(() =>
|
||||||
|
{
|
||||||
using (var ef = efContextFactory.Get())
|
using (var ef = efContextFactory.Get())
|
||||||
{
|
{
|
||||||
migrateSettings(ef);
|
migrateSettings(ef);
|
||||||
@ -48,8 +107,21 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
// Delete the database permanently.
|
// Delete the database permanently.
|
||||||
// Will cause future startups to not attempt migration.
|
// Will cause future startups to not attempt migration.
|
||||||
Logger.Log("Migration successful, deleting EF database", LoggingTarget.Database);
|
log("Migration successful, deleting EF database");
|
||||||
efContextFactory.ResetDatabase();
|
efContextFactory.ResetDatabase();
|
||||||
|
|
||||||
|
if (DebugUtils.IsDebugBuild)
|
||||||
|
Logger.Log("Your development database has been fully migrated to realm. If you switch back to a pre-realm branch and need your previous database, rename the backup file back to \"client.db\".\n\nNote that doing this can potentially leave your file store in a bad state.", level: LogLevel.Important);
|
||||||
|
}, TaskCreationOptions.LongRunning).ContinueWith(t =>
|
||||||
|
{
|
||||||
|
FinishedMigrating = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void log(string message)
|
||||||
|
{
|
||||||
|
Logger.Log(message, LoggingTarget.Database);
|
||||||
|
Scheduler.AddOnce(m => currentOperationText.Text = m, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void migrateBeatmaps(OsuDbContext ef)
|
private void migrateBeatmaps(OsuDbContext ef)
|
||||||
@ -62,12 +134,12 @@ namespace osu.Game.Database
|
|||||||
.Include(s => s.Files).ThenInclude(f => f.FileInfo)
|
.Include(s => s.Files).ThenInclude(f => f.FileInfo)
|
||||||
.Include(s => s.Metadata);
|
.Include(s => s.Metadata);
|
||||||
|
|
||||||
Logger.Log("Beginning beatmaps migration to realm", LoggingTarget.Database);
|
log("Beginning beatmaps migration to realm");
|
||||||
|
|
||||||
// previous entries in EF are removed post migration.
|
// previous entries in EF are removed post migration.
|
||||||
if (!existingBeatmapSets.Any())
|
if (!existingBeatmapSets.Any())
|
||||||
{
|
{
|
||||||
Logger.Log("No beatmaps found to migrate", LoggingTarget.Database);
|
log("No beatmaps found to migrate");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,13 +147,13 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
realmContextFactory.Run(realm =>
|
realmContextFactory.Run(realm =>
|
||||||
{
|
{
|
||||||
Logger.Log($"Found {count} beatmaps in EF", LoggingTarget.Database);
|
log($"Found {count} beatmaps in EF");
|
||||||
|
|
||||||
// only migrate data if the realm database is empty.
|
// only migrate data if the realm database is empty.
|
||||||
// note that this cannot be written as: `realm.All<BeatmapSetInfo>().All(s => s.Protected)`, because realm does not support `.All()`.
|
// note that this cannot be written as: `realm.All<BeatmapSetInfo>().All(s => s.Protected)`, because realm does not support `.All()`.
|
||||||
if (realm.All<BeatmapSetInfo>().Any(s => !s.Protected))
|
if (realm.All<BeatmapSetInfo>().Any(s => !s.Protected))
|
||||||
{
|
{
|
||||||
Logger.Log("Skipping migration as realm already has beatmaps loaded", LoggingTarget.Database);
|
log("Skipping migration as realm already has beatmaps loaded");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -96,7 +168,7 @@ namespace osu.Game.Database
|
|||||||
{
|
{
|
||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
transaction = realm.BeginWrite();
|
transaction = realm.BeginWrite();
|
||||||
Logger.Log($"Migrated {written}/{count} beatmaps...", LoggingTarget.Database);
|
log($"Migrated {written}/{count} beatmaps...");
|
||||||
}
|
}
|
||||||
|
|
||||||
var realmBeatmapSet = new BeatmapSetInfo
|
var realmBeatmapSet = new BeatmapSetInfo
|
||||||
@ -156,7 +228,7 @@ namespace osu.Game.Database
|
|||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Log($"Successfully migrated {count} beatmaps to realm", LoggingTarget.Database);
|
log($"Successfully migrated {count} beatmaps to realm");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -193,12 +265,12 @@ namespace osu.Game.Database
|
|||||||
.Include(s => s.Files)
|
.Include(s => s.Files)
|
||||||
.ThenInclude(f => f.FileInfo);
|
.ThenInclude(f => f.FileInfo);
|
||||||
|
|
||||||
Logger.Log("Beginning scores migration to realm", LoggingTarget.Database);
|
log("Beginning scores migration to realm");
|
||||||
|
|
||||||
// previous entries in EF are removed post migration.
|
// previous entries in EF are removed post migration.
|
||||||
if (!existingScores.Any())
|
if (!existingScores.Any())
|
||||||
{
|
{
|
||||||
Logger.Log("No scores found to migrate", LoggingTarget.Database);
|
log("No scores found to migrate");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,12 +278,12 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
realmContextFactory.Run(realm =>
|
realmContextFactory.Run(realm =>
|
||||||
{
|
{
|
||||||
Logger.Log($"Found {count} scores in EF", LoggingTarget.Database);
|
log($"Found {count} scores in EF");
|
||||||
|
|
||||||
// only migrate data if the realm database is empty.
|
// only migrate data if the realm database is empty.
|
||||||
if (realm.All<ScoreInfo>().Any())
|
if (realm.All<ScoreInfo>().Any())
|
||||||
{
|
{
|
||||||
Logger.Log("Skipping migration as realm already has scores loaded", LoggingTarget.Database);
|
log("Skipping migration as realm already has scores loaded");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -226,7 +298,7 @@ namespace osu.Game.Database
|
|||||||
{
|
{
|
||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
transaction = realm.BeginWrite();
|
transaction = realm.BeginWrite();
|
||||||
Logger.Log($"Migrated {written}/{count} scores...", LoggingTarget.Database);
|
log($"Migrated {written}/{count} scores...");
|
||||||
}
|
}
|
||||||
|
|
||||||
var beatmap = realm.All<BeatmapInfo>().First(b => b.Hash == score.BeatmapInfo.Hash);
|
var beatmap = realm.All<BeatmapInfo>().First(b => b.Hash == score.BeatmapInfo.Hash);
|
||||||
@ -270,7 +342,7 @@ namespace osu.Game.Database
|
|||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Log($"Successfully migrated {count} scores to realm", LoggingTarget.Database);
|
log($"Successfully migrated {count} scores to realm");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -309,7 +381,7 @@ namespace osu.Game.Database
|
|||||||
// note that this cannot be written as: `realm.All<SkinInfo>().All(s => s.Protected)`, because realm does not support `.All()`.
|
// note that this cannot be written as: `realm.All<SkinInfo>().All(s => s.Protected)`, because realm does not support `.All()`.
|
||||||
if (!realm.All<SkinInfo>().Any(s => !s.Protected))
|
if (!realm.All<SkinInfo>().Any(s => !s.Protected))
|
||||||
{
|
{
|
||||||
Logger.Log($"Migrating {existingSkins.Count} skins", LoggingTarget.Database);
|
log($"Migrating {existingSkins.Count} skins");
|
||||||
|
|
||||||
foreach (var skin in existingSkins)
|
foreach (var skin in existingSkins)
|
||||||
{
|
{
|
||||||
@ -358,7 +430,7 @@ namespace osu.Game.Database
|
|||||||
if (!existingSettings.Any())
|
if (!existingSettings.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Logger.Log("Beginning settings migration to realm", LoggingTarget.Database);
|
log("Beginning settings migration to realm");
|
||||||
|
|
||||||
realmContextFactory.Run(realm =>
|
realmContextFactory.Run(realm =>
|
||||||
{
|
{
|
||||||
@ -367,7 +439,7 @@ namespace osu.Game.Database
|
|||||||
// only migrate data if the realm database is empty.
|
// only migrate data if the realm database is empty.
|
||||||
if (!realm.All<RealmRulesetSetting>().Any())
|
if (!realm.All<RealmRulesetSetting>().Any())
|
||||||
{
|
{
|
||||||
Logger.Log($"Migrating {existingSettings.Count} settings", LoggingTarget.Database);
|
log($"Migrating {existingSettings.Count} settings");
|
||||||
|
|
||||||
foreach (var dkb in existingSettings)
|
foreach (var dkb in existingSettings)
|
||||||
{
|
{
|
||||||
@ -396,17 +468,5 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
private string? getRulesetShortNameFromLegacyID(long rulesetId) =>
|
private string? getRulesetShortNameFromLegacyID(long rulesetId) =>
|
||||||
efContextFactory.Get().RulesetInfo.FirstOrDefault(r => r.ID == rulesetId)?.ShortName;
|
efContextFactory.Get().RulesetInfo.FirstOrDefault(r => r.ID == rulesetId)?.ShortName;
|
||||||
|
|
||||||
private void createBackup()
|
|
||||||
{
|
|
||||||
string migration = $"before_final_migration_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}";
|
|
||||||
|
|
||||||
efContextFactory.CreateBackup($"client.{migration}.db");
|
|
||||||
realmContextFactory.CreateBackup($"client.{migration}.realm");
|
|
||||||
|
|
||||||
using (var source = storage.GetStream("collection.db"))
|
|
||||||
using (var destination = storage.GetStream($"collection.{migration}.db", FileAccess.Write, FileMode.CreateNew))
|
|
||||||
source.CopyTo(destination);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,6 +161,11 @@ namespace osu.Game
|
|||||||
|
|
||||||
private readonly BindableNumber<double> globalTrackVolumeAdjust = new BindableNumber<double>(global_track_volume_adjust);
|
private readonly BindableNumber<double> globalTrackVolumeAdjust = new BindableNumber<double>(global_track_volume_adjust);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A legacy EF context factory if migration has not been performed to realm yet.
|
||||||
|
/// </summary>
|
||||||
|
protected DatabaseContextFactory EFContextFactory { get; private set; }
|
||||||
|
|
||||||
public OsuGameBase()
|
public OsuGameBase()
|
||||||
{
|
{
|
||||||
UseDevelopmentServer = DebugUtils.IsDebugBuild;
|
UseDevelopmentServer = DebugUtils.IsDebugBuild;
|
||||||
@ -184,18 +189,28 @@ namespace osu.Game
|
|||||||
|
|
||||||
Resources.AddStore(new DllResourceStore(OsuResources.ResourceAssembly));
|
Resources.AddStore(new DllResourceStore(OsuResources.ResourceAssembly));
|
||||||
|
|
||||||
DatabaseContextFactory efContextFactory = Storage.Exists(DatabaseContextFactory.DATABASE_NAME)
|
if (Storage.Exists(DatabaseContextFactory.DATABASE_NAME))
|
||||||
? new DatabaseContextFactory(Storage)
|
dependencies.Cache(EFContextFactory = new DatabaseContextFactory(Storage));
|
||||||
: null;
|
|
||||||
|
|
||||||
dependencies.Cache(realmFactory = new RealmContextFactory(Storage, "client", efContextFactory));
|
dependencies.Cache(realmFactory = new RealmContextFactory(Storage, "client", EFContextFactory));
|
||||||
|
|
||||||
dependencies.Cache(RulesetStore = new RulesetStore(realmFactory, Storage));
|
dependencies.Cache(RulesetStore = new RulesetStore(realmFactory, Storage));
|
||||||
dependencies.CacheAs<IRulesetStore>(RulesetStore);
|
dependencies.CacheAs<IRulesetStore>(RulesetStore);
|
||||||
|
|
||||||
// A non-null context factory means there's still content to migrate.
|
// Backup is taken here rather than in EFToRealmMigrator to avoid recycling realm contexts
|
||||||
if (efContextFactory != null)
|
// after initial usages below. It can be moved once a direction is established for handling re-subscription.
|
||||||
new EFToRealmMigrator(efContextFactory, realmFactory, LocalConfig, Storage).Run();
|
// See https://github.com/ppy/osu/pull/16547 for more discussion.
|
||||||
|
if (EFContextFactory != null)
|
||||||
|
{
|
||||||
|
string migration = $"before_final_migration_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}";
|
||||||
|
|
||||||
|
EFContextFactory.CreateBackup($"client.{migration}.db");
|
||||||
|
realmFactory.CreateBackup($"client.{migration}.realm");
|
||||||
|
|
||||||
|
using (var source = Storage.GetStream("collection.db"))
|
||||||
|
using (var destination = Storage.GetStream($"collection.{migration}.db", FileAccess.Write, FileMode.CreateNew))
|
||||||
|
source.CopyTo(destination);
|
||||||
|
}
|
||||||
|
|
||||||
dependencies.CacheAs(Storage);
|
dependencies.CacheAs(Storage);
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ using osu.Game.Screens.Menu;
|
|||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Framework.Threading;
|
using osu.Framework.Threading;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Database;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using IntroSequence = osu.Game.Configuration.IntroSequence;
|
using IntroSequence = osu.Game.Configuration.IntroSequence;
|
||||||
|
|
||||||
@ -63,6 +64,11 @@ namespace osu.Game.Screens
|
|||||||
|
|
||||||
protected virtual ShaderPrecompiler CreateShaderPrecompiler() => new ShaderPrecompiler();
|
protected virtual ShaderPrecompiler CreateShaderPrecompiler() => new ShaderPrecompiler();
|
||||||
|
|
||||||
|
[Resolved(canBeNull: true)]
|
||||||
|
private DatabaseContextFactory efContextFactory { get; set; }
|
||||||
|
|
||||||
|
private EFToRealmMigrator realmMigrator;
|
||||||
|
|
||||||
public override void OnEntering(IScreen last)
|
public override void OnEntering(IScreen last)
|
||||||
{
|
{
|
||||||
base.OnEntering(last);
|
base.OnEntering(last);
|
||||||
@ -70,6 +76,10 @@ namespace osu.Game.Screens
|
|||||||
LoadComponentAsync(precompiler = CreateShaderPrecompiler(), AddInternal);
|
LoadComponentAsync(precompiler = CreateShaderPrecompiler(), AddInternal);
|
||||||
LoadComponentAsync(loadableScreen = CreateLoadableScreen());
|
LoadComponentAsync(loadableScreen = CreateLoadableScreen());
|
||||||
|
|
||||||
|
// A non-null context factory means there's still content to migrate.
|
||||||
|
if (efContextFactory != null)
|
||||||
|
LoadComponentAsync(realmMigrator = new EFToRealmMigrator(), AddInternal);
|
||||||
|
|
||||||
LoadComponentAsync(spinner = new LoadingSpinner(true, true)
|
LoadComponentAsync(spinner = new LoadingSpinner(true, true)
|
||||||
{
|
{
|
||||||
Anchor = Anchor.BottomRight,
|
Anchor = Anchor.BottomRight,
|
||||||
@ -86,7 +96,7 @@ namespace osu.Game.Screens
|
|||||||
|
|
||||||
private void checkIfLoaded()
|
private void checkIfLoaded()
|
||||||
{
|
{
|
||||||
if (loadableScreen.LoadState != LoadState.Ready || !precompiler.FinishedCompiling)
|
if (loadableScreen.LoadState != LoadState.Ready || !precompiler.FinishedCompiling || realmMigrator?.FinishedMigrating == false)
|
||||||
{
|
{
|
||||||
Schedule(checkIfLoaded);
|
Schedule(checkIfLoaded);
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user