2023-07-16 21:39:05 +00:00
using System ;
2022-07-11 20:55:54 +00:00
using System.Collections.Generic ;
2022-03-13 22:47:30 +00:00
using System.Collections.ObjectModel ;
2022-05-22 04:27:02 +00:00
using System.IO ;
using System.Linq ;
using System.Net.Http ;
2022-03-13 22:47:30 +00:00
using ReactiveUI ;
using System.Reactive.Disposables ;
using System.Windows.Media.Imaging ;
using ReactiveUI.Fody.Helpers ;
using DynamicData ;
using System.Reactive ;
2022-05-17 03:27:23 +00:00
using System.Reactive.Linq ;
using System.Text.Json ;
2022-03-13 22:47:30 +00:00
using System.Threading ;
using System.Threading.Tasks ;
using System.Windows.Shell ;
2022-08-19 18:13:20 +00:00
using System.Windows.Threading ;
2022-03-13 22:47:30 +00:00
using Microsoft.Extensions.Logging ;
using Microsoft.WindowsAPICodePack.Dialogs ;
using Wabbajack.Common ;
2022-08-19 18:13:20 +00:00
using Wabbajack.Downloaders ;
2022-03-13 22:47:30 +00:00
using Wabbajack.Downloaders.GameFile ;
using Wabbajack.DTOs ;
2022-05-22 04:27:02 +00:00
using Wabbajack.DTOs.DownloadStates ;
2022-03-13 22:47:30 +00:00
using Wabbajack.DTOs.JsonConverters ;
using Wabbajack.Hashing.xxHash64 ;
using Wabbajack.Installer ;
2022-08-19 18:13:20 +00:00
using Wabbajack.LoginManagers ;
2022-03-13 22:47:30 +00:00
using Wabbajack.Messages ;
using Wabbajack.Models ;
using Wabbajack.Paths ;
using Wabbajack.RateLimiter ;
using Wabbajack.Paths.IO ;
using Wabbajack.Services.OSIntegrated ;
using Wabbajack.Util ;
2023-07-16 21:26:45 +00:00
using System.Windows.Forms ;
2022-03-13 22:47:30 +00:00
namespace Wabbajack ;
public enum ModManager
{
Standard
}
public enum InstallState
{
Configuration ,
Installing ,
Success ,
Failure
}
public class InstallerVM : BackNavigatingVM , IBackNavigatingVM , ICpuStatusVM
{
private const string LastLoadedModlist = "last-loaded-modlist" ;
private const string InstallSettingsPrefix = "install-settings-" ;
2022-05-22 04:27:02 +00:00
private Random _random = new ( ) ;
2022-03-13 22:47:30 +00:00
[Reactive]
public Percent StatusProgress { get ; set ; }
[Reactive]
public string StatusText { get ; set ; }
[Reactive]
public ModList ModList { get ; set ; }
[Reactive]
public ModlistMetadata ModlistMetadata { get ; set ; }
[Reactive]
public ErrorResponse ? Completed { get ; set ; }
[Reactive]
public FilePickerVM ModListLocation { get ; set ; }
[Reactive]
public MO2InstallerVM Installer { get ; set ; }
[Reactive]
public BitmapFrame ModListImage { get ; set ; }
[Reactive]
public BitmapFrame SlideShowImage { get ; set ; }
[Reactive]
public InstallState InstallState { get ; set ; }
2022-07-11 20:55:54 +00:00
[Reactive]
protected ErrorResponse [ ] Errors { get ; private set ; }
[Reactive]
public ErrorResponse Error { get ; private set ; }
2022-03-13 22:47:30 +00:00
/// <summary>
/// Slideshow Data
/// </summary>
[Reactive]
public string SlideShowTitle { get ; set ; }
[Reactive]
public string SlideShowAuthor { get ; set ; }
[Reactive]
public string SlideShowDescription { get ; set ; }
private readonly DTOSerializer _dtos ;
private readonly ILogger < InstallerVM > _logger ;
private readonly SettingsManager _settingsManager ;
private readonly IServiceProvider _serviceProvider ;
private readonly SystemParametersConstructor _parametersConstructor ;
private readonly IGameLocator _gameLocator ;
private readonly ResourceMonitor _resourceMonitor ;
private readonly Services . OSIntegrated . Configuration _configuration ;
2022-05-22 04:27:02 +00:00
private readonly HttpClient _client ;
2022-08-19 18:13:20 +00:00
private readonly DownloadDispatcher _downloadDispatcher ;
private readonly IEnumerable < INeedsLogin > _logins ;
2023-05-07 20:32:18 +00:00
private readonly CancellationToken _cancellationToken ;
2022-03-13 22:47:30 +00:00
public ReadOnlyObservableCollection < CPUDisplayVM > StatusList = > _resourceMonitor . Tasks ;
[Reactive]
public bool Installing { get ; set ; }
2022-07-11 20:55:54 +00:00
[Reactive]
public ErrorResponse ErrorState { get ; set ; }
2022-05-22 04:27:02 +00:00
[Reactive]
public bool ShowNSFWSlides { get ; set ; }
public LogStream LoggerProvider { get ; }
2023-07-16 21:26:45 +00:00
private AbsolutePath LastInstallPath { get ; set ; }
2023-10-12 18:33:06 +00:00
[Reactive] public bool OverwriteFiles { get ; set ; }
2022-03-13 22:47:30 +00:00
// Command properties
public ReactiveCommand < Unit , Unit > ShowManifestCommand { get ; }
public ReactiveCommand < Unit , Unit > OpenReadmeCommand { get ; }
2023-10-12 18:33:06 +00:00
public ReactiveCommand < Unit , Unit > OpenWikiCommand { get ; }
2022-05-17 03:27:23 +00:00
public ReactiveCommand < Unit , Unit > OpenDiscordButton { get ; }
2022-03-13 22:47:30 +00:00
public ReactiveCommand < Unit , Unit > VisitModListWebsiteCommand { get ; }
public ReactiveCommand < Unit , Unit > CloseWhenCompleteCommand { get ; }
public ReactiveCommand < Unit , Unit > OpenLogsCommand { get ; }
public ReactiveCommand < Unit , Unit > GoToInstallCommand { get ; }
public ReactiveCommand < Unit , Unit > BeginCommand { get ; }
2022-05-22 04:27:02 +00:00
2022-03-13 22:47:30 +00:00
public InstallerVM ( ILogger < InstallerVM > logger , DTOSerializer dtos , SettingsManager settingsManager , IServiceProvider serviceProvider ,
2022-05-22 04:27:02 +00:00
SystemParametersConstructor parametersConstructor , IGameLocator gameLocator , LogStream loggerProvider , ResourceMonitor resourceMonitor ,
2023-05-07 20:32:18 +00:00
Wabbajack . Services . OSIntegrated . Configuration configuration , HttpClient client , DownloadDispatcher dispatcher , IEnumerable < INeedsLogin > logins ,
CancellationToken cancellationToken ) : base ( logger )
2022-03-13 22:47:30 +00:00
{
_logger = logger ;
_configuration = configuration ;
LoggerProvider = loggerProvider ;
_settingsManager = settingsManager ;
_dtos = dtos ;
_serviceProvider = serviceProvider ;
_parametersConstructor = parametersConstructor ;
_gameLocator = gameLocator ;
_resourceMonitor = resourceMonitor ;
2022-05-22 04:27:02 +00:00
_client = client ;
2022-08-19 18:13:20 +00:00
_downloadDispatcher = dispatcher ;
_logins = logins ;
2023-05-07 20:32:18 +00:00
_cancellationToken = cancellationToken ;
2022-03-13 22:47:30 +00:00
Installer = new MO2InstallerVM ( this ) ;
BackCommand = ReactiveCommand . Create ( ( ) = > NavigateToGlobal . Send ( NavigateToGlobal . ScreenType . ModeSelectionView ) ) ;
BeginCommand = ReactiveCommand . Create ( ( ) = > BeginInstall ( ) . FireAndForget ( ) ) ;
2023-05-07 20:32:18 +00:00
2022-03-13 22:47:30 +00:00
OpenReadmeCommand = ReactiveCommand . Create ( ( ) = >
{
UIUtils . OpenWebsite ( new Uri ( ModList ! . Readme ) ) ;
2023-05-07 20:32:18 +00:00
} , this . WhenAnyValue ( vm = > vm . LoadingLock . IsNotLoading , vm = > vm . ModList . Readme , ( isNotLoading , readme ) = > isNotLoading & & ! string . IsNullOrWhiteSpace ( readme ) ) ) ;
2023-10-12 18:33:06 +00:00
OpenWikiCommand = ReactiveCommand . Create ( ( ) = >
{
UIUtils . OpenWebsite ( new Uri ( "https://wiki.wabbajack.org/index.html" ) ) ;
} , this . WhenAnyValue ( vm = > vm . LoadingLock . IsNotLoading ) ) ;
2022-03-13 22:47:30 +00:00
VisitModListWebsiteCommand = ReactiveCommand . Create ( ( ) = >
{
UIUtils . OpenWebsite ( ModList ! . Website ) ;
} , LoadingLock . IsNotLoadingObservable ) ;
ModListLocation = new FilePickerVM
{
ExistCheckOption = FilePickerVM . CheckOptions . On ,
PathType = FilePickerVM . PathTypeOptions . File ,
PromptTitle = "Select a ModList to install"
} ;
ModListLocation . Filters . Add ( new CommonFileDialogFilter ( "Wabbajack Modlist" , "*.wabbajack" ) ) ;
OpenLogsCommand = ReactiveCommand . Create ( ( ) = >
{
UIUtils . OpenFolder ( _configuration . LogLocation ) ;
} ) ;
2022-05-17 03:27:23 +00:00
OpenDiscordButton = ReactiveCommand . Create ( ( ) = >
{
UIUtils . OpenWebsite ( new Uri ( ModlistMetadata . Links . DiscordURL ) ) ;
} , this . WhenAnyValue ( x = > x . ModlistMetadata )
. WhereNotNull ( )
. Select ( md = > ! string . IsNullOrWhiteSpace ( md . Links . DiscordURL ) ) ) ;
2022-03-13 22:47:30 +00:00
2022-05-17 03:27:23 +00:00
ShowManifestCommand = ReactiveCommand . Create ( ( ) = >
{
UIUtils . OpenWebsite ( new Uri ( "https://www.wabbajack.org/search/" + ModlistMetadata . NamespacedName ) ) ;
} , this . WhenAnyValue ( x = > x . ModlistMetadata )
. WhereNotNull ( )
. Select ( md = > ! string . IsNullOrWhiteSpace ( md . Links . MachineURL ) ) ) ;
2022-05-16 23:02:40 +00:00
CloseWhenCompleteCommand = ReactiveCommand . Create ( ( ) = >
{
Environment . Exit ( 0 ) ;
} ) ;
2022-03-13 22:47:30 +00:00
GoToInstallCommand = ReactiveCommand . Create ( ( ) = >
{
UIUtils . OpenFolder ( Installer . Location . TargetPath ) ;
} ) ;
2023-10-12 18:33:06 +00:00
this . WhenAnyValue ( x = > x . OverwriteFiles )
. Subscribe ( x = > ConfirmOverwrite ( ) ) ;
2022-03-13 22:47:30 +00:00
MessageBus . Current . Listen < LoadModlistForInstalling > ( )
2023-07-16 21:22:24 +00:00
. Subscribe ( msg = > LoadModlistFromGallery ( msg . Path , msg . Metadata ) . FireAndForget ( ) )
2022-03-13 22:47:30 +00:00
. DisposeWith ( CompositeDisposable ) ;
MessageBus . Current . Listen < LoadLastLoadedModlist > ( )
. Subscribe ( msg = >
{
LoadLastModlist ( ) . FireAndForget ( ) ;
} ) ;
this . WhenActivated ( disposables = >
{
ModListLocation . WhenAnyValue ( l = > l . TargetPath )
. Subscribe ( p = > LoadModlist ( p , null ) . FireAndForget ( ) )
. DisposeWith ( disposables ) ;
2022-05-22 04:27:02 +00:00
var token = new CancellationTokenSource ( ) ;
BeginSlideShow ( token . Token ) . FireAndForget ( ) ;
Disposable . Create ( ( ) = > token . Cancel ( ) )
. DisposeWith ( disposables ) ;
2022-07-11 20:55:54 +00:00
this . WhenAny ( vm = > vm . ModListLocation . ErrorState )
. CombineLatest ( this . WhenAny ( vm = > vm . Installer . DownloadLocation . ErrorState ) ,
this . WhenAny ( vm = > vm . Installer . Location . ErrorState ) ,
this . WhenAny ( vm = > vm . ModListLocation . TargetPath ) ,
this . WhenAny ( vm = > vm . Installer . Location . TargetPath ) ,
this . WhenAny ( vm = > vm . Installer . DownloadLocation . TargetPath ) )
. Select ( t = >
{
var errors = new [ ] { t . First , t . Second , t . Third }
. Where ( t = > t . Failed )
. Concat ( Validate ( ) )
. ToArray ( ) ;
if ( ! errors . Any ( ) ) return ErrorResponse . Success ;
return ErrorResponse . Fail ( string . Join ( "\n" , errors . Select ( e = > e . Reason ) ) ) ;
} )
. BindTo ( this , vm = > vm . ErrorState )
. DisposeWith ( disposables ) ;
2022-03-13 22:47:30 +00:00
} ) ;
}
2022-07-11 20:55:54 +00:00
private IEnumerable < ErrorResponse > Validate ( )
{
if ( ! ModListLocation . TargetPath . FileExists ( ) )
yield return ErrorResponse . Fail ( "Mod list source does not exist" ) ;
var downloadPath = Installer . DownloadLocation . TargetPath ;
if ( downloadPath . Depth < = 1 )
yield return ErrorResponse . Fail ( "Download path isn't set to a folder" ) ;
var installPath = Installer . Location . TargetPath ;
if ( installPath . Depth < = 1 )
yield return ErrorResponse . Fail ( "Install path isn't set to a folder" ) ;
if ( installPath . InFolder ( KnownFolders . Windows ) )
yield return ErrorResponse . Fail ( "Don't install modlists into your Windows folder" ) ;
2023-07-16 21:20:49 +00:00
if ( installPath . ToString ( ) . Length > 0 & & downloadPath . ToString ( ) . Length > 0 & & installPath = = downloadPath )
{
yield return ErrorResponse . Fail ( "Can't have identical install and download folders" ) ;
}
2023-10-12 18:33:06 +00:00
if ( installPath . ToString ( ) . Length > 0 & & downloadPath . ToString ( ) . Length > 0 & & KnownFolders . IsSubDirectoryOf ( installPath . ToString ( ) , downloadPath . ToString ( ) ) )
{
yield return ErrorResponse . Fail ( "Can't put the install folder inside the download folder" ) ;
}
2022-09-20 23:18:32 +00:00
foreach ( var game in GameRegistry . Games )
{
if ( ! _gameLocator . TryFindLocation ( game . Key , out var location ) )
continue ;
if ( installPath . InFolder ( location ) )
yield return ErrorResponse . Fail ( "Can't install a modlist into a game folder" ) ;
if ( location . ThisAndAllParents ( ) . Any ( path = > installPath = = path ) )
{
yield return ErrorResponse . Fail (
"Can't install in this path, installed files may overwrite important game files" ) ;
}
}
if ( installPath . InFolder ( KnownFolders . EntryPoint ) )
yield return ErrorResponse . Fail ( "Can't install a modlist into the Wabbajack.exe path" ) ;
2023-07-16 21:21:22 +00:00
if ( downloadPath . InFolder ( KnownFolders . EntryPoint ) )
yield return ErrorResponse . Fail ( "Can't download a modlist into the Wabbajack.exe path" ) ;
2022-09-20 23:18:32 +00:00
if ( KnownFolders . EntryPoint . ThisAndAllParents ( ) . Any ( path = > installPath = = path ) )
{
yield return ErrorResponse . Fail ( "Installing in this folder may overwrite Wabbajack" ) ;
}
2023-07-16 21:26:45 +00:00
2023-10-12 18:33:06 +00:00
if ( installPath . ToString ( ) . Length ! = 0 & & installPath ! = LastInstallPath & & ! OverwriteFiles & &
2023-07-16 21:26:45 +00:00
Directory . EnumerateFileSystemEntries ( installPath . ToString ( ) ) . Any ( ) )
{
2023-10-12 18:33:06 +00:00
yield return ErrorResponse . Fail ( "There are files in the install folder, please tick 'Overwrite Installation' to confirm you want to install to this folder " + Environment . NewLine +
"if you are updating an existing modlist, then this is expected and can be overwritten." ) ;
2023-07-16 21:39:05 +00:00
}
2023-07-16 21:26:45 +00:00
2023-07-16 21:22:56 +00:00
if ( KnownFolders . IsInSpecialFolder ( installPath ) | | KnownFolders . IsInSpecialFolder ( downloadPath ) )
{
2023-10-12 18:33:06 +00:00
yield return ErrorResponse . Fail ( "Can't install into Windows locations such as Documents etc, please make a new folder for the modlist - C:\\ModList\\ for example." ) ;
2023-07-16 21:22:56 +00:00
}
2023-10-12 18:33:06 +00:00
// Disabled Because it was causing issues for people trying to update lists.
//if (installPath.ToString().Length > 0 && downloadPath.ToString().Length > 0 && !HasEnoughSpace(installPath, downloadPath)){
// yield return ErrorResponse.Fail("Can't install modlist due to lack of free hard drive space, please read the modlist Readme to learn more.");
//}
2022-07-11 20:55:54 +00:00
}
2023-10-12 18:33:06 +00:00
/ *
private bool HasEnoughSpace ( AbsolutePath inpath , AbsolutePath downpath )
{
string driveLetterInPath = inpath . ToString ( ) . Substring ( 0 , 1 ) ;
string driveLetterDownPath = inpath . ToString ( ) . Substring ( 0 , 1 ) ;
DriveInfo driveUsedInPath = new DriveInfo ( driveLetterInPath ) ;
DriveInfo driveUsedDownPath = new DriveInfo ( driveLetterDownPath ) ;
long spaceRequiredforInstall = ModlistMetadata . DownloadMetadata . SizeOfInstalledFiles ;
long spaceRequiredforDownload = ModlistMetadata . DownloadMetadata . SizeOfArchives ;
long spaceInstRemaining = driveUsedInPath . AvailableFreeSpace ;
long spaceDownRemaining = driveUsedDownPath . AvailableFreeSpace ;
if ( driveLetterInPath = = driveLetterDownPath )
{
long totalSpaceRequired = spaceRequiredforInstall + spaceRequiredforDownload ;
if ( spaceInstRemaining < totalSpaceRequired )
{
return false ;
}
} else
{
if ( spaceInstRemaining < spaceRequiredforInstall | | spaceDownRemaining < spaceRequiredforDownload )
{
return false ;
}
}
return true ;
} * /
2022-05-22 04:27:02 +00:00
private async Task BeginSlideShow ( CancellationToken token )
{
while ( ! token . IsCancellationRequested )
{
await Task . Delay ( 5000 , token ) ;
if ( InstallState = = InstallState . Installing )
{
await PopulateNextModSlide ( ModList ) ;
}
}
}
2022-03-13 22:47:30 +00:00
private async Task LoadLastModlist ( )
{
var lst = await _settingsManager . Load < AbsolutePath > ( LastLoadedModlist ) ;
if ( lst . FileExists ( ) )
2023-05-07 20:32:18 +00:00
{
ModListLocation . TargetPath = lst ;
}
2022-03-13 22:47:30 +00:00
}
2023-07-16 21:22:24 +00:00
private async Task LoadModlistFromGallery ( AbsolutePath path , ModlistMetadata metadata )
{
ModListLocation . TargetPath = path ;
ModlistMetadata = metadata ;
}
2022-03-13 22:47:30 +00:00
private async Task LoadModlist ( AbsolutePath path , ModlistMetadata ? metadata )
{
using var ll = LoadingLock . WithLoading ( ) ;
InstallState = InstallState . Configuration ;
ModListLocation . TargetPath = path ;
try
{
ModList = await StandardInstaller . LoadFromFile ( _dtos , path ) ;
ModListImage = BitmapFrame . Create ( await StandardInstaller . ModListImageStream ( path ) ) ;
2022-10-14 21:04:41 +00:00
if ( ! string . IsNullOrWhiteSpace ( ModList . Readme ) )
UIUtils . OpenWebsite ( new Uri ( ModList . Readme ) ) ;
2022-03-13 22:47:30 +00:00
StatusText = $"Install configuration for {ModList.Name}" ;
TaskBarUpdate . Send ( $"Loaded {ModList.Name}" , TaskbarItemProgressState . Normal ) ;
var hex = ( await ModListLocation . TargetPath . ToString ( ) . Hash ( ) ) . ToHex ( ) ;
var prevSettings = await _settingsManager . Load < SavedInstallSettings > ( InstallSettingsPrefix + hex ) ;
2022-05-17 03:27:23 +00:00
if ( path . WithExtension ( Ext . MetaData ) . FileExists ( ) )
{
try
{
metadata = JsonSerializer . Deserialize < ModlistMetadata > ( await path . WithExtension ( Ext . MetaData )
. ReadAllTextAsync ( ) ) ;
ModlistMetadata = metadata ;
}
catch ( Exception ex )
{
_logger . LogInformation ( ex , "Can't load metadata cached next to file" ) ;
}
}
2022-03-13 22:47:30 +00:00
if ( prevSettings . ModListLocation = = path )
{
ModListLocation . TargetPath = prevSettings . ModListLocation ;
2023-07-16 21:26:45 +00:00
LastInstallPath = prevSettings . InstallLocation ;
2022-03-13 22:47:30 +00:00
Installer . Location . TargetPath = prevSettings . InstallLocation ;
Installer . DownloadLocation . TargetPath = prevSettings . DownloadLoadction ;
ModlistMetadata = metadata ? ? prevSettings . Metadata ;
}
PopulateSlideShow ( ModList ) ;
ll . Succeed ( ) ;
await _settingsManager . Save ( LastLoadedModlist , path ) ;
}
catch ( Exception ex )
{
_logger . LogError ( ex , "While loading modlist" ) ;
ll . Fail ( ) ;
}
}
2023-10-12 18:33:06 +00:00
private void ConfirmOverwrite ( )
{
AbsolutePath prev = Installer . Location . TargetPath ;
Installer . Location . TargetPath = "" . ToAbsolutePath ( ) ;
Installer . Location . TargetPath = prev ;
}
2022-03-13 22:47:30 +00:00
private async Task BeginInstall ( )
{
2022-05-17 05:26:59 +00:00
await Task . Run ( async ( ) = >
2022-03-13 22:47:30 +00:00
{
2022-05-17 05:26:59 +00:00
InstallState = InstallState . Installing ;
2022-08-19 18:13:20 +00:00
foreach ( var downloader in await _downloadDispatcher . AllDownloaders ( ModList . Archives . Select ( a = > a . State ) ) )
{
_logger . LogInformation ( "Preparing {Name}" , downloader . GetType ( ) . Name ) ;
if ( await downloader . Prepare ( ) )
continue ;
var manager = _logins
. FirstOrDefault ( l = > l . LoginFor ( ) = = downloader . GetType ( ) ) ;
if ( manager = = null )
{
_logger . LogError ( "Cannot install, could not prepare {Name} for downloading" ,
downloader . GetType ( ) . Name ) ;
throw new Exception ( $"No way to prepare {downloader}" ) ;
}
RxApp . MainThreadScheduler . Schedule ( manager , ( _ , _ ) = >
{
manager . TriggerLogin . Execute ( null ) ;
return Disposable . Empty ;
} ) ;
while ( true )
{
if ( await downloader . Prepare ( ) )
break ;
await Task . Delay ( 1000 ) ;
}
}
2022-05-17 05:26:59 +00:00
var postfix = ( await ModListLocation . TargetPath . ToString ( ) . Hash ( ) ) . ToHex ( ) ;
await _settingsManager . Save ( InstallSettingsPrefix + postfix , new SavedInstallSettings
2022-03-13 22:47:30 +00:00
{
2022-05-17 05:26:59 +00:00
ModListLocation = ModListLocation . TargetPath ,
InstallLocation = Installer . Location . TargetPath ,
DownloadLoadction = Installer . DownloadLocation . TargetPath ,
Metadata = ModlistMetadata
2022-03-13 22:47:30 +00:00
} ) ;
2022-08-18 23:02:19 +00:00
await _settingsManager . Save ( LastLoadedModlist , ModListLocation . TargetPath ) ;
2022-03-13 22:47:30 +00:00
2022-05-17 05:26:59 +00:00
try
2022-03-13 22:47:30 +00:00
{
2022-05-17 05:26:59 +00:00
var installer = StandardInstaller . Create ( _serviceProvider , new InstallerConfiguration
{
Game = ModList . GameType ,
Downloads = Installer . DownloadLocation . TargetPath ,
Install = Installer . Location . TargetPath ,
ModList = ModList ,
ModlistArchive = ModListLocation . TargetPath ,
SystemParameters = _parametersConstructor . Create ( ) ,
GameFolder = _gameLocator . GameLocation ( ModList . GameType )
} ) ;
2022-03-13 22:47:30 +00:00
2022-05-17 05:26:59 +00:00
installer . OnStatusUpdate = update = >
{
StatusText = update . StatusText ;
StatusProgress = update . StepsProgress ;
TaskBarUpdate . Send ( update . StatusText , TaskbarItemProgressState . Indeterminate ,
update . StepsProgress . Value ) ;
} ;
2023-05-07 20:32:18 +00:00
if ( ! await installer . Begin ( _cancellationToken ) )
2022-05-17 05:26:59 +00:00
{
TaskBarUpdate . Send ( $"Error during install of {ModList.Name}" , TaskbarItemProgressState . Error ) ;
InstallState = InstallState . Failure ;
StatusText = $"Error during install of {ModList.Name}" ;
StatusProgress = Percent . Zero ;
}
else
{
TaskBarUpdate . Send ( $"Finished install of {ModList.Name}" , TaskbarItemProgressState . Normal ) ;
InstallState = InstallState . Success ;
2022-10-14 21:04:41 +00:00
if ( ! string . IsNullOrWhiteSpace ( ModList . Readme ) )
UIUtils . OpenWebsite ( new Uri ( ModList . Readme ) ) ;
2022-05-17 05:26:59 +00:00
}
}
catch ( Exception ex )
2022-05-16 23:02:40 +00:00
{
TaskBarUpdate . Send ( $"Error during install of {ModList.Name}" , TaskbarItemProgressState . Error ) ;
2022-08-12 23:03:35 +00:00
_logger . LogError ( ex , ex . Message ) ;
2022-05-16 23:02:40 +00:00
InstallState = InstallState . Failure ;
StatusText = $"Error during install of {ModList.Name}" ;
StatusProgress = Percent . Zero ;
}
2022-05-17 05:26:59 +00:00
} ) ;
2022-03-13 22:47:30 +00:00
}
class SavedInstallSettings
{
public AbsolutePath ModListLocation { get ; set ; }
public AbsolutePath InstallLocation { get ; set ; }
public AbsolutePath DownloadLoadction { get ; set ; }
public ModlistMetadata Metadata { get ; set ; }
}
private void PopulateSlideShow ( ModList modList )
{
2023-10-12 18:33:06 +00:00
if ( ModlistMetadata . ImageContainsTitle & & ModlistMetadata . DisplayVersionOnlyInInstallerView )
{
SlideShowTitle = "v" + ModlistMetadata . Version . ToString ( ) ;
}
else
{
SlideShowTitle = modList . Name ;
}
2022-03-13 22:47:30 +00:00
SlideShowAuthor = modList . Author ;
SlideShowDescription = modList . Description ;
SlideShowImage = ModListImage ;
}
2022-05-22 04:27:02 +00:00
private async Task PopulateNextModSlide ( ModList modList )
{
try
{
var mods = modList . Archives . Select ( a = > a . State )
. OfType < IMetaState > ( )
. Where ( t = > ShowNSFWSlides | | ! t . IsNSFW )
. Where ( t = > t . ImageURL ! = null )
. ToArray ( ) ;
var thisMod = mods [ _random . Next ( 0 , mods . Length ) ] ;
var data = await _client . GetByteArrayAsync ( thisMod . ImageURL ! ) ;
var image = BitmapFrame . Create ( new MemoryStream ( data ) ) ;
SlideShowTitle = thisMod . Name ;
SlideShowAuthor = thisMod . Author ;
SlideShowDescription = thisMod . Description ;
SlideShowImage = image ;
}
catch ( Exception ex )
{
2022-12-28 16:21:58 +00:00
_logger . LogTrace ( ex , "While loading slide" ) ;
2022-05-22 04:27:02 +00:00
}
}
2023-10-12 18:33:06 +00:00
}