diff --git a/Nebula.Launcher/ViewModels/MainViewModel.cs b/Nebula.Launcher/ViewModels/MainViewModel.cs index 4903dd1..36ff3ac 100644 --- a/Nebula.Launcher/ViewModels/MainViewModel.cs +++ b/Nebula.Launcher/ViewModels/MainViewModel.cs @@ -40,6 +40,7 @@ public partial class MainViewModel : ViewModelBase [GenerateProperty] private DebugService DebugService { get; } = default!; [GenerateProperty] private PopupMessageService PopupMessageService { get; } = default!; [GenerateProperty, DesignConstruct] private ViewHelperService ViewHelperService { get; } = default!; + [GenerateProperty] private FileService FileService { get; } = default!; public ObservableCollection Items { get; private set; } @@ -56,6 +57,20 @@ public partial class MainViewModel : ViewModelBase PopupMessageService.OnPopupRequired += OnPopupRequired; PopupMessageService.OnCloseRequired += OnPopupCloseRequired; + + CheckMigration(); + } + + private void CheckMigration() + { + var loadingHandler = ViewHelperService.GetViewModel(); + loadingHandler.LoadingName = "Migration task, please wait..."; + loadingHandler.IsCancellable = false; + + if (!FileService.CheckMigration(loadingHandler)) + return; + + OnPopupRequired(loadingHandler); } partial void OnSelectedListItemChanged(ListItemTemplate? value) diff --git a/Nebula.Launcher/ViewModels/Popup/LoadingContextViewModel.cs b/Nebula.Launcher/ViewModels/Popup/LoadingContextViewModel.cs index 5cf5bdb..6e39aab 100644 --- a/Nebula.Launcher/ViewModels/Popup/LoadingContextViewModel.cs +++ b/Nebula.Launcher/ViewModels/Popup/LoadingContextViewModel.cs @@ -17,6 +17,7 @@ public sealed partial class LoadingContextViewModel : PopupViewModelBase, ILoadi [ObservableProperty] private int _resolvedJobs; public string LoadingName { get; set; } = "Loading..."; + public bool IsCancellable { get; set; } = true; public override bool IsClosable => false; public override string Title => LoadingName; @@ -42,6 +43,7 @@ public sealed partial class LoadingContextViewModel : PopupViewModelBase, ILoadi } public void Cancel(){ + if(!IsCancellable) return; CancellationService.Cancel(); Dispose(); } diff --git a/Nebula.Launcher/Views/Popup/LoadingContextView.axaml b/Nebula.Launcher/Views/Popup/LoadingContextView.axaml index 644c382..4fee167 100644 --- a/Nebula.Launcher/Views/Popup/LoadingContextView.axaml +++ b/Nebula.Launcher/Views/Popup/LoadingContextView.axaml @@ -24,7 +24,11 @@ - diff --git a/Nebula.Shared/Services/FileService.cs b/Nebula.Shared/Services/FileService.cs index b3a8822..bcc9404 100644 --- a/Nebula.Shared/Services/FileService.cs +++ b/Nebula.Shared/Services/FileService.cs @@ -26,17 +26,46 @@ public class FileService EngineFileApi = CreateFileApi("engine"); ManifestFileApi = CreateFileApi("manifest"); ConfigurationApi = CreateFileApi("config"); + } - // Some migrating think - foreach(var file in ContentFileApi.AllFiles){ - if(file.Contains("\\") || !ContentFileApi.TryOpen(file, out var stream)) continue; - - ContentFileApi.Save(HashApi.GetManifestPath(file), stream); - stream.Dispose(); - ContentFileApi.Remove(file); + public bool CheckMigration(ILoadingHandler loadingHandler) + { + _debugService.Log("Checking migration..."); + + var migrationList = ContentFileApi.AllFiles.Where(f => !f.Contains("\\")).ToList(); + if(migrationList.Count == 0) return false; + + _debugService.Log($"Found {migrationList.Count} migration files. Starting migration..."); + Task.Run(() => DoMigration(loadingHandler, migrationList)); + return true; + } + + private void DoMigration(ILoadingHandler loadingHandler, List migrationList) + { + loadingHandler.SetJobsCount(migrationList.Count); + + Parallel.ForEach(migrationList, (f,_)=>MigrateFile(f,loadingHandler)); + + if (loadingHandler is IDisposable disposable) + { + disposable.Dispose(); } } + private void MigrateFile(string file, ILoadingHandler loadingHandler) + { + if(!ContentFileApi.TryOpen(file, out var stream)) + { + loadingHandler.AppendResolvedJob(); + return; + } + + ContentFileApi.Save(HashApi.GetManifestPath(file), stream); + stream.Dispose(); + ContentFileApi.Remove(file); + loadingHandler.AppendResolvedJob(); + } + public IReadWriteFileApi CreateFileApi(string path) { return new FileApi(Path.Join(RootPath, path)); @@ -60,4 +89,66 @@ public class FileService throw; } } +} + +public sealed class ConsoleLoadingHandler : ILoadingHandler +{ + private int _currJobs; + + private float _percent; + private int _resolvedJobs; + + public void SetJobsCount(int count) + { + _currJobs = count; + + UpdatePercent(); + Draw(); + } + + public int GetJobsCount() + { + return _currJobs; + } + + public void SetResolvedJobsCount(int count) + { + _resolvedJobs = count; + + UpdatePercent(); + Draw(); + } + + public int GetResolvedJobsCount() + { + return _resolvedJobs; + } + + private void UpdatePercent() + { + if (_currJobs == 0) + { + _percent = 0; + return; + } + + if (_resolvedJobs > _currJobs) return; + + _percent = _resolvedJobs / (float)_currJobs; + } + + private void Draw() + { + var barCount = 10; + var fullCount = (int)(barCount * _percent); + var emptyCount = barCount - fullCount; + + Console.Write("\r"); + + for (var i = 0; i < fullCount; i++) Console.Write("#"); + + for (var i = 0; i < emptyCount; i++) Console.Write(" "); + + Console.Write($"\t {_resolvedJobs}/{_currJobs}"); + } } \ No newline at end of file