public ModsViewModel(IScreen screen, DowModLoader?dowModService = null) : base(screen, "mods") { this.logger = this.Log(); this.dowModService = dowModService ?? Locator.Current.GetService <DowModLoader>(); var whenNotLoading = this.WhenAnyValue(x => x.Loading).Select(loading => !loading).DistinctUntilChanged(); var whenItemSelected = this.WhenAnyValue(x => x.SelectedBaseItem, x => x.SelectedModItem, (baseItem, modItem) => baseItem != null || modItem != null).DistinctUntilChanged(); var canLoadSpecific = whenNotLoading.CombineLatest(whenItemSelected, (notLoading, itemSelected) => notLoading && itemSelected).DistinctUntilChanged(); ReloadMods = ReactiveCommand.CreateFromTask(LoadAllMods, whenNotLoading); RefreshMods = ReactiveCommand.CreateFromTask(GetModsAsync); RefreshMods.ThrownExceptions.Subscribe(exception => logger.Error(exception)); RefreshMods.Execute().Subscribe(); RefreshMods.Select(mods => mods.Where(x => !x.Module.File.IsVanilla)) .Subscribe(mods => { ModItems.Clear(); ModItems.AddRange(mods); }); RefreshMods.Select(mods => mods.Where(x => x.Module.File.IsVanilla)) .Subscribe(mods => { BaseGameItems.Clear(); BaseGameItems.AddRange(mods); }); }
private async Task LoadAllMods() { using var store = new ModsDataStore(); store.DropAll(); Dictionary <string, UnloadedMod> allUnloaded = BaseGameItems.Concat(ModItems) .GroupBy(item => item.Module.File.ModFolder, item => item.Module) .ToDictionary(g => g.Key, g => g.First()); foreach (var item in BaseGameItems.Concat(ModItems)) { item.IsLoaded = false; } var memo = new LoadMemo(); foreach (var item in BaseGameItems.Concat(ModItems).Where(mod => mod.Module.File.Playable)) { DowMod mod = await Observable.Start(() => dowModService.LoadMod(item.Module, allUnloaded, memo), RxApp.TaskpoolScheduler); store.Add(mod); item.IsLoaded = true; } // Yeah this is kind of weird. But essentially we want to load the playable mods first. // This is because they likely depend on the non-playable mods. Non-playable mods may be // sub-modules for playable mods. As such they might have Locales that reference the parent mod // for this reason we want to ensure that we load from the root. foreach (var item in BaseGameItems.Concat(ModItems).Where(mod => !mod.Module.File.Playable)) { DowMod mod = dowModService.LoadMod(item.Module, allUnloaded, memo); store.Add(mod); item.IsLoaded = true; } }