mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Merge pull request #94 from Noggog/SlideshowView
Migrated more slideshow concepts away from AppState
This commit is contained in:
commit
fc60eadab3
@ -25,19 +25,16 @@ using Wabbajack.UI;
|
||||
using DynamicData;
|
||||
using DynamicData.Binding;
|
||||
using System.Reactive;
|
||||
using System.Text;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
public enum TaskMode { INSTALLING, BUILDING }
|
||||
public class AppState : ViewModel, IDataErrorInfo
|
||||
{
|
||||
public const bool GcCollect = true;
|
||||
|
||||
private SlideShow _slideShow;
|
||||
public SlideShow Slideshow { get; }
|
||||
|
||||
private string _mo2Folder;
|
||||
|
||||
private readonly BitmapImage _wabbajackLogo = UIUtils.BitmapImageFromResource("Wabbajack.UI.banner.png");
|
||||
public readonly BitmapImage _noneImage = UIUtils.BitmapImageFromResource("Wabbajack.UI.none.jpg");
|
||||
|
||||
private readonly Subject<CPUStatus> _statusSubject = new Subject<CPUStatus>();
|
||||
@ -49,21 +46,12 @@ namespace Wabbajack
|
||||
private string _ModListPath;
|
||||
public string ModListPath { get => _ModListPath; private set => this.RaiseAndSetIfChanged(ref _ModListPath, value); }
|
||||
|
||||
private TaskMode _Mode;
|
||||
public TaskMode Mode { get => _Mode; private set => this.RaiseAndSetIfChanged(ref _Mode, value); }
|
||||
private RunMode _Mode;
|
||||
public RunMode Mode { get => _Mode; private set => this.RaiseAndSetIfChanged(ref _Mode, value); }
|
||||
|
||||
private string _ModListName;
|
||||
public string ModListName { get => _ModListName; set => this.RaiseAndSetIfChanged(ref _ModListName, value); }
|
||||
|
||||
private bool _EnableSlideShow = true;
|
||||
public bool EnableSlideShow { get => _EnableSlideShow; set => this.RaiseAndSetIfChanged(ref _EnableSlideShow, value); }
|
||||
|
||||
private BitmapImage _SplashScreenImage;
|
||||
public BitmapImage SplashScreenImage { get => _SplashScreenImage; set => this.RaiseAndSetIfChanged(ref _SplashScreenImage, value); }
|
||||
|
||||
private BitmapImage _NextIcon = UIUtils.BitmapImageFromResource("Wabbajack.UI.Icons.next.png");
|
||||
public BitmapImage NextIcon { get => _NextIcon; set => this.RaiseAndSetIfChanged(ref _NextIcon, value); }
|
||||
|
||||
private bool _UIReady;
|
||||
public bool UIReady { get => _UIReady; set => this.RaiseAndSetIfChanged(ref _UIReady, value); }
|
||||
|
||||
@ -78,12 +66,10 @@ namespace Wabbajack
|
||||
public IReactiveCommand ChangeDownloadPathCommand { get; }
|
||||
public IReactiveCommand BeginCommand { get; }
|
||||
public IReactiveCommand ShowReportCommand { get; }
|
||||
public IReactiveCommand VisitNexusSiteCommand { get; }
|
||||
public IReactiveCommand OpenReadmeCommand { get; }
|
||||
public IReactiveCommand OpenModListPropertiesCommand { get; }
|
||||
public IReactiveCommand SlideShowNextItemCommand { get; } = ReactiveCommand.Create(() => { });
|
||||
|
||||
public AppState(TaskMode mode)
|
||||
public AppState(RunMode mode)
|
||||
{
|
||||
if (Path.GetDirectoryName(Assembly.GetEntryAssembly().Location.ToLower()) == KnownFolders.Downloads.Path.ToLower())
|
||||
{
|
||||
@ -102,103 +88,21 @@ namespace Wabbajack
|
||||
this.ChangePathCommand = ReactiveCommand.Create(ExecuteChangePath);
|
||||
this.ChangeDownloadPathCommand = ReactiveCommand.Create(ExecuteChangeDownloadPath);
|
||||
this.ShowReportCommand = ReactiveCommand.Create(ShowReport);
|
||||
this.VisitNexusSiteCommand = ReactiveCommand.Create(VisitNexusSite);
|
||||
this.OpenModListPropertiesCommand = ReactiveCommand.Create(OpenModListProperties);
|
||||
this.OpenModListPropertiesCommand = ReactiveCommand.Create(
|
||||
execute: OpenModListProperties,
|
||||
canExecute: this.WhenAny(x => x.UIReady)
|
||||
.ObserveOnGuiThread());
|
||||
this.OpenReadmeCommand = ReactiveCommand.Create(
|
||||
execute: this.OpenReadmeWindow,
|
||||
canExecute: Observable.CombineLatest(
|
||||
this.WhenAny(x => x.ModList)
|
||||
.Select(modList => !string.IsNullOrEmpty(modList?.Readme)),
|
||||
this.WhenAny(x => x.UIReady),
|
||||
resultSelector: (modListExists, uiReady) => modListExists && uiReady)
|
||||
canExecute: this.WhenAny(x => x.ModList)
|
||||
.Select(modList => !string.IsNullOrEmpty(modList?.Readme))
|
||||
.ObserveOnGuiThread());
|
||||
this.BeginCommand = ReactiveCommand.Create(
|
||||
execute: this.ExecuteBegin,
|
||||
canExecute: this.WhenAny(x => x.UIReady)
|
||||
.ObserveOnGuiThread());
|
||||
|
||||
// Apply modlist properties when it changes
|
||||
this.WhenAny(x => x.ModList)
|
||||
.NotNull()
|
||||
.Subscribe(modList =>
|
||||
{
|
||||
this.SplashScreenModName = modList.Name;
|
||||
this.SplashScreenAuthorName = modList.Author;
|
||||
this._nexusSiteURL = modList.Website;
|
||||
this.SplashScreenSummary = modList.Description;
|
||||
})
|
||||
.DisposeWith(this.CompositeDisposable);
|
||||
|
||||
_slideShow = new SlideShow(this, true);
|
||||
|
||||
// Update splashscreen when modlist changes
|
||||
Observable.CombineLatest(
|
||||
this.WhenAny(x => x.ModList),
|
||||
this.WhenAny(x => x.ModListPath),
|
||||
this.WhenAny(x => x.EnableSlideShow),
|
||||
(modList, modListPath, enableSlideShow) => (modList, modListPath, enableSlideShow))
|
||||
// Do any potential unzipping on a background thread
|
||||
.ObserveOn(RxApp.TaskpoolScheduler)
|
||||
.Select(u =>
|
||||
{
|
||||
if (u.enableSlideShow
|
||||
&& u.modList != null
|
||||
&& u.modListPath != null
|
||||
&& File.Exists(u.modListPath)
|
||||
&& !string.IsNullOrEmpty(u.modList.Image)
|
||||
&& u.modList.Image.Length == 36)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var fs = new FileStream(u.modListPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var ar = new ZipArchive(fs, ZipArchiveMode.Read))
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
var entry = ar.GetEntry(u.modList.Image);
|
||||
using (var e = entry.Open())
|
||||
e.CopyTo(ms);
|
||||
var image = new BitmapImage();
|
||||
image.BeginInit();
|
||||
image.CacheOption = BitmapCacheOption.OnLoad;
|
||||
image.StreamSource = ms;
|
||||
image.EndInit();
|
||||
image.Freeze();
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
this.LogMsg("Error loading splash image.");
|
||||
}
|
||||
}
|
||||
return _wabbajackLogo;
|
||||
})
|
||||
.ObserveOn(RxApp.MainThreadScheduler)
|
||||
.StartWith(_wabbajackLogo)
|
||||
.Subscribe(bitmap => this.SplashScreenImage = bitmap)
|
||||
.DisposeWith(this.CompositeDisposable);
|
||||
|
||||
/// Wire slideshow updates
|
||||
// Merge all the sources that trigger a slideshow update
|
||||
Observable.Merge(
|
||||
// If the natural timer fires
|
||||
Observable.Interval(TimeSpan.FromSeconds(10)).Unit(),
|
||||
// If user requests one manually
|
||||
this.SlideShowNextItemCommand.StartingExecution())
|
||||
// When enabled, fire an initial signal
|
||||
.StartWith(Unit.Default)
|
||||
// Only subscribe to slideshow triggers if enabled and installing
|
||||
.FilterSwitch(
|
||||
Observable.CombineLatest(
|
||||
this.WhenAny(x => x.EnableSlideShow),
|
||||
this.WhenAny(x => x.Installing),
|
||||
resultSelector: (enabled, installing) => enabled && installing))
|
||||
// Don't ever update more than once every half second. ToDo: Update to debounce
|
||||
.Throttle(TimeSpan.FromMilliseconds(500), RxApp.MainThreadScheduler)
|
||||
.ObserveOn(RxApp.MainThreadScheduler)
|
||||
.Subscribe(_ => _slideShow.UpdateSlideShowItem())
|
||||
.DisposeWith(this.CompositeDisposable);
|
||||
this.Slideshow = new SlideShow(this);
|
||||
|
||||
// Initialize work queue
|
||||
WorkQueue.Init(
|
||||
@ -235,18 +139,22 @@ namespace Wabbajack
|
||||
|
||||
private void ExecuteChangePath()
|
||||
{
|
||||
if (Mode == TaskMode.INSTALLING)
|
||||
switch (this.Mode)
|
||||
{
|
||||
var folder = UIUtils.ShowFolderSelectionDialog("Select Installation directory");
|
||||
if (folder == null) return;
|
||||
Location = folder;
|
||||
if (DownloadLocation == null)
|
||||
DownloadLocation = Path.Combine(Location, "downloads");
|
||||
}
|
||||
else
|
||||
{
|
||||
var folder = UIUtils.ShowFolderSelectionDialog("Select Your MO2 profile directory");
|
||||
Location = folder;
|
||||
case RunMode.Compile:
|
||||
Location = UIUtils.ShowFolderSelectionDialog("Select Your MO2 profile directory");
|
||||
break;
|
||||
case RunMode.Install:
|
||||
var folder = UIUtils.ShowFolderSelectionDialog("Select Installation directory");
|
||||
if (folder == null) return;
|
||||
Location = folder;
|
||||
if (DownloadLocation == null)
|
||||
{
|
||||
DownloadLocation = Path.Combine(Location, "downloads");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,15 +171,6 @@ namespace Wabbajack
|
||||
Process.Start(file);
|
||||
}
|
||||
|
||||
public string _nexusSiteURL = null;
|
||||
private void VisitNexusSite()
|
||||
{
|
||||
if (_nexusSiteURL != null && _nexusSiteURL.StartsWith("https://"))
|
||||
{
|
||||
Process.Start(_nexusSiteURL);
|
||||
}
|
||||
}
|
||||
|
||||
private ModlistPropertiesWindow modlistPropertiesWindow;
|
||||
public string newImagePath;
|
||||
public string readmePath;
|
||||
@ -299,39 +198,25 @@ namespace Wabbajack
|
||||
|
||||
private void OpenReadmeWindow()
|
||||
{
|
||||
if (!UIReady || string.IsNullOrEmpty(this.ModList.Readme)) return;
|
||||
var text = "";
|
||||
if (string.IsNullOrEmpty(this.ModList.Readme)) return;
|
||||
using (var fs = new FileStream(this.ModListPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var ar = new ZipArchive(fs, ZipArchiveMode.Read))
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
var entry = ar.GetEntry(this.ModList.Readme);
|
||||
using (var e = entry.Open())
|
||||
e.CopyTo(ms);
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
using (var sr = new StreamReader(ms))
|
||||
{
|
||||
string line;
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
text += line+Environment.NewLine;
|
||||
e.CopyTo(ms);
|
||||
}
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
using (var reader = new StreamReader(ms))
|
||||
{
|
||||
var viewer = new TextViewer(reader.ReadToEnd(), this.ModListName);
|
||||
viewer.Show();
|
||||
}
|
||||
}
|
||||
|
||||
var viewer = new TextViewer(text, this.ModListName);
|
||||
viewer.Show();
|
||||
}
|
||||
|
||||
private string _SplashScreenModName = "Wabbajack";
|
||||
public string SplashScreenModName { get => _SplashScreenModName; set => this.RaiseAndSetIfChanged(ref _SplashScreenModName, value); }
|
||||
|
||||
private string _SplashScreenAuthorName = "Halgari & the Wabbajack Team";
|
||||
public string SplashScreenAuthorName { get => _SplashScreenAuthorName; set => this.RaiseAndSetIfChanged(ref _SplashScreenAuthorName, value); }
|
||||
|
||||
private string _SplashScreenSummary;
|
||||
public string SplashScreenSummary { get => _SplashScreenSummary; set => this.RaiseAndSetIfChanged(ref _SplashScreenSummary, value); }
|
||||
private bool _splashShowNSFW = false;
|
||||
public bool SplashShowNSFW { get => _splashShowNSFW; set => this.RaiseAndSetIfChanged(ref _splashShowNSFW, value); }
|
||||
|
||||
public string Error => "Error";
|
||||
|
||||
public string this[string columnName] => Validate(columnName);
|
||||
@ -348,15 +233,15 @@ namespace Wabbajack
|
||||
}
|
||||
else switch (Mode)
|
||||
{
|
||||
case TaskMode.BUILDING when Location != null && Directory.Exists(Location) && File.Exists(Path.Combine(Location, "modlist.txt")):
|
||||
case RunMode.Compile when Location != null && Directory.Exists(Location) && File.Exists(Path.Combine(Location, "modlist.txt")):
|
||||
Location = Path.Combine(Location, "modlist.txt");
|
||||
validationMessage = null;
|
||||
ConfigureForBuild();
|
||||
break;
|
||||
case TaskMode.INSTALLING when Location != null && Directory.Exists(Location) && !Directory.EnumerateFileSystemEntries(Location).Any():
|
||||
case RunMode.Install when Location != null && Directory.Exists(Location) && !Directory.EnumerateFileSystemEntries(Location).Any():
|
||||
validationMessage = null;
|
||||
break;
|
||||
case TaskMode.INSTALLING when Location != null && Directory.Exists(Location) && Directory.EnumerateFileSystemEntries(Location).Any():
|
||||
case RunMode.Install when Location != null && Directory.Exists(Location) && Directory.EnumerateFileSystemEntries(Location).Any():
|
||||
validationMessage = "You have selected a non-empty directory. Installing the modlist here might result in a broken install!";
|
||||
break;
|
||||
default:
|
||||
@ -390,7 +275,7 @@ namespace Wabbajack
|
||||
|
||||
var profile_name = Path.GetFileName(profile_folder);
|
||||
this.ModListName = profile_name;
|
||||
Mode = TaskMode.BUILDING;
|
||||
this.Mode = RunMode.Compile;
|
||||
|
||||
var tmp_compiler = new Compiler(mo2folder);
|
||||
DownloadLocation = tmp_compiler.MO2DownloadsFolder;
|
||||
@ -402,12 +287,12 @@ namespace Wabbajack
|
||||
{
|
||||
this.ModList = modlist;
|
||||
this.ModListPath = source;
|
||||
Mode = TaskMode.INSTALLING;
|
||||
this.Mode = RunMode.Install;
|
||||
ModListName = this.ModList.Name;
|
||||
HTMLReport = this.ModList.ReportHTML;
|
||||
Location = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
|
||||
_slideShow.SlideShowElements = modlist.Archives
|
||||
this.Slideshow.SlideShowElements = modlist.Archives
|
||||
.Select(m => m.State)
|
||||
.OfType<NexusDownloader.State>()
|
||||
.Select(m =>
|
||||
@ -416,13 +301,13 @@ namespace Wabbajack
|
||||
m.Adult,m.NexusURL,m.SlideShowPic)).ToList();
|
||||
|
||||
|
||||
_slideShow.PreloadSlideShow();
|
||||
this.Slideshow.PreloadSlideShow();
|
||||
}
|
||||
|
||||
private void ExecuteBegin()
|
||||
{
|
||||
UIReady = false;
|
||||
if (Mode == TaskMode.INSTALLING)
|
||||
if (this.Mode == RunMode.Install)
|
||||
{
|
||||
this.Installing = true;
|
||||
var installer = new Installer(this.ModListPath, this.ModList, Location)
|
||||
@ -459,11 +344,11 @@ namespace Wabbajack
|
||||
var compiler = new Compiler(_mo2Folder)
|
||||
{
|
||||
MO2Profile = ModListName,
|
||||
ModListName = ChangedProperties ? SplashScreenModName : null,
|
||||
ModListAuthor = ChangedProperties ? SplashScreenAuthorName : null,
|
||||
ModListDescription = ChangedProperties ? SplashScreenSummary : null,
|
||||
ModListName = ChangedProperties ? this.Slideshow.ModName : null,
|
||||
ModListAuthor = ChangedProperties ? this.Slideshow.AuthorName : null,
|
||||
ModListDescription = ChangedProperties ? this.Slideshow.Summary : null,
|
||||
ModListImage = ChangedProperties ? newImagePath : null,
|
||||
ModListWebsite = ChangedProperties ? _nexusSiteURL : null,
|
||||
ModListWebsite = ChangedProperties ? this.Slideshow.NexusSiteURL : null,
|
||||
ModListReadme = ChangedProperties ? readmePath : null
|
||||
};
|
||||
var th = new Thread(() =>
|
||||
|
14
Wabbajack/Enums/RunMode.cs
Normal file
14
Wabbajack/Enums/RunMode.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
public enum RunMode
|
||||
{
|
||||
Compile,
|
||||
Install
|
||||
}
|
||||
}
|
@ -277,11 +277,11 @@ namespace Wabbajack.NexusApi
|
||||
}
|
||||
|
||||
|
||||
public static IEnumerable<UI.Slide> CachedSlideShow
|
||||
public static IEnumerable<Slide> CachedSlideShow
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Directory.Exists(Consts.NexusCacheDirectory)) return new UI.Slide[] { };
|
||||
if (!Directory.Exists(Consts.NexusCacheDirectory)) return new Slide[] { };
|
||||
|
||||
return Directory.EnumerateFiles(Consts.NexusCacheDirectory)
|
||||
.Where(f => f.EndsWith(".json"))
|
||||
@ -299,7 +299,7 @@ namespace Wabbajack.NexusApi
|
||||
})
|
||||
.Where(m => m != null)
|
||||
.Where(m => m._internal_version == CACHED_VERSION_NUMBER && m.picture_url != null)
|
||||
.Select(m => new UI.Slide(m.name,m.mod_id,m.summary,m.author,m.contains_adult_content,GetModURL(m.game_name,m.mod_id),m.picture_url));
|
||||
.Select(m => new Slide(m.name,m.mod_id,m.summary,m.author,m.contains_adult_content,GetModURL(m.game_name,m.mod_id),m.picture_url));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1146,7 +1146,7 @@
|
||||
</Style>
|
||||
|
||||
|
||||
<Style TargetType="{x:Type Button}">
|
||||
<Style TargetType="{x:Type Button}" x:Key="MainButtonStyle" >
|
||||
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
|
||||
<Setter Property="Background" Value="{StaticResource ButtonBackground}"/>
|
||||
<Setter Property="BorderBrush" Value="{StaticResource ButtonBorder}"/>
|
||||
@ -1187,6 +1187,7 @@
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style BasedOn="{StaticResource MainButtonStyle}" TargetType="{x:Type Button}" />
|
||||
|
||||
<!-- ToggleButton-->
|
||||
<Style TargetType="{x:Type ToggleButton}">
|
||||
|
@ -45,127 +45,13 @@
|
||||
<TextBlock FontSize="16" Text="{Binding ModListName}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Properties -->
|
||||
<Grid
|
||||
Name="PropertyCompilerGrid"
|
||||
<local:SlideshowView
|
||||
x:Name="Slideshow"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="0,0,2,4">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="30" />
|
||||
</Grid.RowDefinitions>
|
||||
<Image
|
||||
Grid.Row="0"
|
||||
Margin="0,0,0,4"
|
||||
Source="{Binding SplashScreenImage}"
|
||||
Stretch="Fill" />
|
||||
<Button
|
||||
Grid.Row="1"
|
||||
Height="30"
|
||||
Command="{Binding OpenModListPropertiesCommand}"
|
||||
IsEnabled="{Binding UIReady}">
|
||||
<TextBlock
|
||||
FontSize="15"
|
||||
FontWeight="Bold"
|
||||
Text="Modlist Properties" />
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid
|
||||
Name="PropertyInstallerGrid"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="0,0,2,4">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="30" />
|
||||
</Grid.RowDefinitions>
|
||||
<Image
|
||||
Grid.Row="0"
|
||||
Source="{Binding SplashScreenImage}"
|
||||
Stretch="Fill" />
|
||||
<Button
|
||||
Grid.Row="1"
|
||||
Height="30"
|
||||
Command="{Binding OpenReadmeCommand}">
|
||||
<TextBlock
|
||||
FontSize="15"
|
||||
FontWeight="Bold"
|
||||
Text="Open README" />
|
||||
</Button>
|
||||
</Grid>
|
||||
<!-- End Properties -->
|
||||
|
||||
<!-- Slideshow -->
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="2,0,0,4">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
FontSize="30"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding SplashScreenModName}" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
FontSize="15"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding SplashScreenAuthorName}" />
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
FontSize="15"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding SplashScreenSummary}"
|
||||
TextWrapping="Wrap" />
|
||||
<Grid Grid.Row="3" VerticalAlignment="Bottom">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="48" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<CheckBox
|
||||
Name="EnableSlideShow"
|
||||
Grid.Column="0"
|
||||
Margin="0,10,0,0"
|
||||
IsChecked="{Binding EnableSlideShow}">
|
||||
Enable the Slideshow
|
||||
</CheckBox>
|
||||
<CheckBox
|
||||
Name="ShowNSFWContent"
|
||||
Grid.Column="1"
|
||||
Margin="4,10,0,0"
|
||||
IsChecked="{Binding SplashShowNSFW}">
|
||||
Show NSFW Mods in the Slideshow
|
||||
</CheckBox>
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
Height="30"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding SlideShowNextItemCommand}"
|
||||
ToolTip="Skip to next slide">
|
||||
<DockPanel>
|
||||
<Image Source="{Binding NextIcon}" Stretch="Fill" />
|
||||
</DockPanel>
|
||||
</Button>
|
||||
</Grid>
|
||||
<Button
|
||||
Grid.Row="4"
|
||||
Height="30"
|
||||
Command="{Binding VisitNexusSiteCommand}">
|
||||
<TextBlock
|
||||
FontSize="15"
|
||||
FontWeight="Bold"
|
||||
Text="View Nexus Site" />
|
||||
</Button>
|
||||
</Grid>
|
||||
<!-- End Slideshow -->
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="0,0,0,4"
|
||||
DataContext="{Binding Slideshow}" />
|
||||
|
||||
<ProgressBar
|
||||
Grid.Row="2"
|
||||
|
@ -16,19 +16,13 @@ namespace Wabbajack
|
||||
{
|
||||
private AppState _state;
|
||||
|
||||
public enum RunMode
|
||||
{
|
||||
Compile,
|
||||
Install
|
||||
}
|
||||
|
||||
public MainWindow(RunMode mode, string source)
|
||||
{
|
||||
var args = Environment.GetCommandLineArgs();
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
var context = new AppState(TaskMode.BUILDING);
|
||||
var context = new AppState(RunMode.Install);
|
||||
context.LogMsg($"Wabbajack Build - {ThisAssembly.Git.Sha}");
|
||||
SetupHandlers(context);
|
||||
DataContext = context;
|
||||
@ -36,19 +30,6 @@ namespace Wabbajack
|
||||
Utils.SetLoggerFn(s => context.LogMsg(s));
|
||||
Utils.SetStatusFn((msg, progress) => WorkQueue.Report(msg, progress));
|
||||
|
||||
_state._nexusSiteURL = "https://github.com/wabbajack-tools/wabbajack";
|
||||
|
||||
if (mode == RunMode.Compile)
|
||||
{
|
||||
PropertyCompilerGrid.Visibility = Visibility.Visible;
|
||||
PropertyInstallerGrid.Visibility = Visibility.Hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
PropertyCompilerGrid.Visibility = Visibility.Hidden;
|
||||
PropertyInstallerGrid.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
new Thread(() =>
|
||||
{
|
||||
if (mode == RunMode.Compile)
|
||||
|
@ -7,8 +7,7 @@
|
||||
mc:Ignorable="d"
|
||||
Title="Wabbajack (Modlist Properties)" Height="600" Width="900"
|
||||
Style="{StaticResource {x:Type Window}}" Icon="Icons/wabbajack.ico" WindowStyle="ToolWindow"
|
||||
ResizeMode="NoResize"
|
||||
Closing="Window_Closing">
|
||||
ResizeMode="NoResize">
|
||||
<Grid Margin="8">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="300"/>
|
||||
|
@ -22,11 +22,6 @@ namespace Wabbajack
|
||||
state = _state;
|
||||
}
|
||||
|
||||
private void Window_Closing(object sender, CancelEventArgs e)
|
||||
{
|
||||
//Hide();
|
||||
}
|
||||
|
||||
private void SetSplashScreen_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var file = UIUtils.OpenFileDialog("Banner image|*.png");
|
||||
@ -45,13 +40,13 @@ namespace Wabbajack
|
||||
{
|
||||
BitmapImage splashScreen = new BitmapImage(new Uri(newBannerFile));
|
||||
state.newImagePath = newBannerFile;
|
||||
state.SplashScreenImage = splashScreen;
|
||||
state.Slideshow.Image = splashScreen;
|
||||
}
|
||||
|
||||
state.SplashScreenModName = ModlistNameProperty.Text;
|
||||
state.SplashScreenSummary = ModlistDescriptionProperty.Text;
|
||||
state.SplashScreenAuthorName = ModlistAuthorProperty.Text;
|
||||
state._nexusSiteURL = ModlistWebsiteProperty.Text;
|
||||
state.Slideshow.ModName = ModlistNameProperty.Text;
|
||||
state.Slideshow.Summary = ModlistDescriptionProperty.Text;
|
||||
state.Slideshow.AuthorName = ModlistAuthorProperty.Text;
|
||||
state.Slideshow.NexusSiteURL = ModlistWebsiteProperty.Text;
|
||||
state.readmePath = ModlistReadmeProperty.Text;
|
||||
|
||||
state.ChangedProperties = true;
|
||||
|
@ -1,14 +1,20 @@
|
||||
using System;
|
||||
using ReactiveUI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media.Imaging;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.NexusApi;
|
||||
|
||||
namespace Wabbajack.UI
|
||||
namespace Wabbajack
|
||||
{
|
||||
public class Slide
|
||||
{
|
||||
@ -34,29 +40,145 @@ namespace Wabbajack.UI
|
||||
|
||||
}
|
||||
|
||||
internal class SlideShow
|
||||
public class SlideShow : ViewModel
|
||||
{
|
||||
private readonly Random _random;
|
||||
private Slide _lastSlide;
|
||||
private const bool UseSync = false;
|
||||
private const int MaxCacheSize = 10;
|
||||
private readonly AppState _appState;
|
||||
|
||||
public SlideShow(AppState appState, bool checkCache)
|
||||
public List<Slide> SlideShowElements { get; set; }
|
||||
|
||||
public Dictionary<string, Slide> CachedSlides { get; }
|
||||
|
||||
public Queue<Slide> SlidesQueue { get; }
|
||||
|
||||
public AppState AppState { get; }
|
||||
|
||||
public BitmapImage NextIcon { get; } = UIUtils.BitmapImageFromResource("Wabbajack.UI.Icons.next.png");
|
||||
public BitmapImage WabbajackLogo { get; } = UIUtils.BitmapImageFromResource("Wabbajack.UI.banner.png");
|
||||
|
||||
private bool _ShowNSFW;
|
||||
public bool ShowNSFW { get => _ShowNSFW; set => this.RaiseAndSetIfChanged(ref _ShowNSFW, value); }
|
||||
|
||||
private bool _GCAfterUpdating = true;
|
||||
public bool GCAfterUpdating { get => _GCAfterUpdating; set => this.RaiseAndSetIfChanged(ref _GCAfterUpdating, value); }
|
||||
|
||||
private bool _Enable = true;
|
||||
public bool Enable { get => _Enable; set => this.RaiseAndSetIfChanged(ref _Enable, value); }
|
||||
|
||||
private BitmapImage _Image;
|
||||
public BitmapImage Image { get => _Image; set => this.RaiseAndSetIfChanged(ref _Image, value); }
|
||||
|
||||
private string _ModName = "Wabbajack";
|
||||
public string ModName { get => _ModName; set => this.RaiseAndSetIfChanged(ref _ModName, value); }
|
||||
|
||||
private string _AuthorName = "Halgari & the Wabbajack Team";
|
||||
public string AuthorName { get => _AuthorName; set => this.RaiseAndSetIfChanged(ref _AuthorName, value); }
|
||||
|
||||
private string _Summary;
|
||||
public string Summary { get => _Summary; set => this.RaiseAndSetIfChanged(ref _Summary, value); }
|
||||
|
||||
private string _NexusSiteURL = "https://github.com/wabbajack-tools/wabbajack";
|
||||
public string NexusSiteURL { get => _NexusSiteURL; set => this.RaiseAndSetIfChanged(ref _NexusSiteURL, value); }
|
||||
|
||||
public IReactiveCommand SlideShowNextItemCommand { get; } = ReactiveCommand.Create(() => { });
|
||||
public IReactiveCommand VisitNexusSiteCommand { get; }
|
||||
|
||||
public SlideShow(AppState appState)
|
||||
{
|
||||
SlideShowElements = new List<Slide>();
|
||||
SlideShowElements = NexusApiClient.CachedSlideShow.ToList();
|
||||
CachedSlides = new Dictionary<string, Slide>();
|
||||
SlidesQueue = new Queue<Slide>();
|
||||
_random = new Random();
|
||||
_appState = appState;
|
||||
AppState = appState;
|
||||
|
||||
if (!checkCache) return;
|
||||
IEnumerable<Slide> files = NexusApiClient.CachedSlideShow;
|
||||
IEnumerable<Slide> enumerable = files.ToList();
|
||||
if (enumerable.Any())
|
||||
{
|
||||
SlideShowElements = enumerable.ToList();
|
||||
}
|
||||
this.VisitNexusSiteCommand = ReactiveCommand.Create(
|
||||
execute: () => Process.Start(this.NexusSiteURL),
|
||||
canExecute: this.WhenAny(x => x.NexusSiteURL)
|
||||
.Select(x => x?.StartsWith("https://") ?? false)
|
||||
.ObserveOnGuiThread());
|
||||
|
||||
// Apply modlist properties when it changes
|
||||
this.WhenAny(x => x.AppState.ModList)
|
||||
.NotNull()
|
||||
.Subscribe(modList =>
|
||||
{
|
||||
this.NexusSiteURL = modList.Website;
|
||||
this.ModName = modList.Name;
|
||||
this.AuthorName = modList.Author;
|
||||
this.Summary = modList.Description;
|
||||
})
|
||||
.DisposeWith(this.CompositeDisposable);
|
||||
|
||||
// Update splashscreen when modlist changes
|
||||
Observable.CombineLatest(
|
||||
(this).WhenAny(x => x.AppState.ModList),
|
||||
(this).WhenAny(x => x.AppState.ModListPath),
|
||||
(this).WhenAny(x => x.Enable),
|
||||
(modList, modListPath, enabled) => (modList, modListPath, enabled))
|
||||
// Do any potential unzipping on a background thread
|
||||
.ObserveOn(RxApp.TaskpoolScheduler)
|
||||
.Select(u =>
|
||||
{
|
||||
if (u.enabled
|
||||
&& u.modList != null
|
||||
&& u.modListPath != null
|
||||
&& File.Exists(u.modListPath)
|
||||
&& !string.IsNullOrEmpty(u.modList.Image)
|
||||
&& u.modList.Image.Length == 36)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var fs = new FileStream(u.modListPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var ar = new ZipArchive(fs, ZipArchiveMode.Read))
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
var entry = ar.GetEntry(u.modList.Image);
|
||||
using (var e = entry.Open())
|
||||
e.CopyTo(ms);
|
||||
var image = new BitmapImage();
|
||||
image.BeginInit();
|
||||
image.CacheOption = BitmapCacheOption.OnLoad;
|
||||
image.StreamSource = ms;
|
||||
image.EndInit();
|
||||
image.Freeze();
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
this.AppState.LogMsg("Error loading splash image.");
|
||||
}
|
||||
}
|
||||
return this.WabbajackLogo;
|
||||
})
|
||||
.ObserveOn(RxApp.MainThreadScheduler)
|
||||
.StartWith(this.WabbajackLogo)
|
||||
.Subscribe(bitmap => this.Image = bitmap)
|
||||
.DisposeWith(this.CompositeDisposable);
|
||||
|
||||
/// Wire slideshow updates
|
||||
// Merge all the sources that trigger a slideshow update
|
||||
Observable.Merge(
|
||||
// If the natural timer fires
|
||||
Observable.Interval(TimeSpan.FromSeconds(10)).Unit(),
|
||||
// If user requests one manually
|
||||
this.SlideShowNextItemCommand.StartingExecution())
|
||||
// When enabled, fire an initial signal
|
||||
.StartWith(Unit.Default)
|
||||
// Only subscribe to slideshow triggers if enabled and installing
|
||||
.FilterSwitch(
|
||||
Observable.CombineLatest(
|
||||
this.WhenAny(x => x.Enable),
|
||||
this.WhenAny(x => x.AppState.Installing),
|
||||
resultSelector: (enabled, installing) => enabled && installing))
|
||||
// Don't ever update more than once every half second. ToDo: Update to debounce
|
||||
.Throttle(TimeSpan.FromMilliseconds(500), RxApp.MainThreadScheduler)
|
||||
.ObserveOn(RxApp.MainThreadScheduler)
|
||||
.Subscribe(_ => this.UpdateSlideShowItem())
|
||||
.DisposeWith(this.CompositeDisposable);
|
||||
}
|
||||
|
||||
public void PreloadSlideShow()
|
||||
@ -89,23 +211,23 @@ namespace Wabbajack.UI
|
||||
|
||||
//if (SlidesQueue.Contains(randomSlide)) continue;
|
||||
CachedSlides.Remove(randomSlide.ModID);
|
||||
if (AppState.GcCollect)
|
||||
if (this.GCAfterUpdating)
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
if (!slide.IsNSFW || (slide.IsNSFW && ShowNSFW))
|
||||
{
|
||||
_appState.SplashScreenImage = _appState._noneImage;
|
||||
this.Image = AppState._noneImage;
|
||||
if (slide.ImageURL != null && slide.Image != null)
|
||||
{
|
||||
if (!CachedSlides.ContainsKey(slide.ModID)) return;
|
||||
_appState.SplashScreenImage = slide.Image;
|
||||
this.Image = slide.Image;
|
||||
}
|
||||
|
||||
_appState.SplashScreenModName = slide.ModName;
|
||||
_appState.SplashScreenAuthorName = slide.ModAuthor;
|
||||
_appState.SplashScreenSummary = slide.ModDescription;
|
||||
_appState._nexusSiteURL = slide.ModURL;
|
||||
this.ModName = slide.ModName;
|
||||
this.AuthorName = slide.ModAuthor;
|
||||
this.Summary = slide.ModDescription;
|
||||
this.NexusSiteURL = slide.ModURL;
|
||||
}
|
||||
|
||||
SlidesQueue.Dequeue();
|
||||
@ -194,12 +316,5 @@ namespace Wabbajack.UI
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool ShowNSFW { get; set; }
|
||||
public List<Slide> SlideShowElements { get; set; }
|
||||
|
||||
public Dictionary<string, Slide> CachedSlides { get; }
|
||||
|
||||
public Queue<Slide> SlidesQueue { get; }
|
||||
}
|
||||
}
|
122
Wabbajack/UI/SlideshowView.xaml
Normal file
122
Wabbajack/UI/SlideshowView.xaml
Normal file
@ -0,0 +1,122 @@
|
||||
<UserControl
|
||||
x:Class="Wabbajack.SlideshowView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Wabbajack"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DataContext="{d:DesignInstance local:SlideShow}"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="4" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
Grid.Column="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="30" />
|
||||
</Grid.RowDefinitions>
|
||||
<Image
|
||||
Grid.Row="0"
|
||||
Source="{Binding Image}"
|
||||
Stretch="Fill" />
|
||||
<Button
|
||||
Grid.Row="1"
|
||||
FontSize="15"
|
||||
FontWeight="Bold">
|
||||
<Button.Style>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource MainButtonStyle}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding AppState.Mode}" Value="{x:Static local:RunMode.Install}">
|
||||
<Setter Property="Command" Value="{Binding AppState.OpenReadmeCommand}" />
|
||||
<Setter Property="Content" Value="Open README" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding AppState.Mode}" Value="{x:Static local:RunMode.Compile}">
|
||||
<Setter Property="Command" Value="{Binding AppState.OpenModListPropertiesCommand}" />
|
||||
<Setter Property="Content" Value="Modlist Properties" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
Grid.Column="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
FontSize="30"
|
||||
FontWeight="Bold"
|
||||
Margin="6,0,0,0"
|
||||
Text="{Binding ModName}" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
FontSize="15"
|
||||
FontWeight="Bold"
|
||||
Margin="6,0,0,6"
|
||||
Text="{Binding AuthorName}" />
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
FontSize="15"
|
||||
FontWeight="Bold"
|
||||
Padding="5"
|
||||
Background="{StaticResource TextBoxBackground}"
|
||||
Text="{Binding Summary}"
|
||||
TextWrapping="Wrap" />
|
||||
<Grid Grid.Row="3" VerticalAlignment="Bottom">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="48" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<CheckBox
|
||||
Margin="6,0,0,0"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
IsChecked="{Binding Enable}">
|
||||
Enable the Slideshow
|
||||
</CheckBox>
|
||||
<CheckBox
|
||||
Grid.Column="1"
|
||||
Margin="15,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
IsChecked="{Binding ShowNSFW}">
|
||||
Show NSFW Mods in the Slideshow
|
||||
</CheckBox>
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
Height="30"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding SlideShowNextItemCommand}"
|
||||
ToolTip="Skip to next slide">
|
||||
<DockPanel>
|
||||
<Image Source="{Binding NextIcon}" Stretch="Fill" />
|
||||
</DockPanel>
|
||||
</Button>
|
||||
</Grid>
|
||||
<Button
|
||||
Grid.Row="4"
|
||||
Height="30"
|
||||
Command="{Binding VisitNexusSiteCommand}">
|
||||
<TextBlock
|
||||
FontSize="15"
|
||||
FontWeight="Bold"
|
||||
Text="View Nexus Site" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
28
Wabbajack/UI/SlideshowView.xaml.cs
Normal file
28
Wabbajack/UI/SlideshowView.xaml.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for SlideshowView.xaml
|
||||
/// </summary>
|
||||
public partial class SlideshowView : UserControl
|
||||
{
|
||||
public SlideshowView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
@ -236,7 +236,11 @@
|
||||
<Compile Include="Downloaders\MegaDownloader.cs" />
|
||||
<Compile Include="Downloaders\ModDBDownloader.cs" />
|
||||
<Compile Include="Downloaders\NexusDownloader.cs" />
|
||||
<Compile Include="Enums\RunMode.cs" />
|
||||
<Compile Include="Extensions\ReactiveUIExt.cs" />
|
||||
<Compile Include="UI\SlideshowView.xaml.cs">
|
||||
<DependentUpon>SlideshowView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="UI\ModlistPropertiesWindow.xaml.cs">
|
||||
<DependentUpon>ModlistPropertiesWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@ -258,6 +262,10 @@
|
||||
<Compile Include="Validation\ValidateModlist.cs" />
|
||||
<Compile Include="ViewModel.cs" />
|
||||
<Compile Include="zEditIntegration.cs" />
|
||||
<Page Include="UI\SlideshowView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="UI\MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
|
Loading…
Reference in New Issue
Block a user