Moved a lot of slideshow logic into Slideshow.cs

This commit is contained in:
Justin Swanson 2019-10-13 14:53:49 -05:00
parent be5e740b57
commit c5a049664a
4 changed files with 127 additions and 113 deletions

View File

@ -34,7 +34,6 @@ namespace Wabbajack
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>();
@ -52,15 +51,6 @@ namespace Wabbajack
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,7 +68,6 @@ namespace Wabbajack
public IReactiveCommand VisitNexusSiteCommand { get; }
public IReactiveCommand OpenReadmeCommand { get; }
public IReactiveCommand OpenModListPropertiesCommand { get; }
public IReactiveCommand SlideShowNextItemCommand { get; } = ReactiveCommand.Create(() => { });
public AppState(RunMode mode)
{
@ -119,84 +108,12 @@ namespace Wabbajack
.NotNull()
.Subscribe(modList =>
{
this.SplashScreenModName = modList.Name;
this.SplashScreenAuthorName = modList.Author;
this._nexusSiteURL = modList.Website;
this.SplashScreenSummary = modList.Description;
})
.DisposeWith(this.CompositeDisposable);
this.Slideshow = new SlideShow(this);
// 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(_ => this.Slideshow.UpdateSlideShowItem())
.DisposeWith(this.CompositeDisposable);
// Initialize work queue
WorkQueue.Init(
report_function: (id, msg, progress) => this._statusSubject.OnNext(new CPUStatus() { ID = id, Msg = msg, Progress = progress }),
@ -322,14 +239,6 @@ namespace Wabbajack
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); }
@ -460,9 +369,9 @@ 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.SplashScreenModName : null,
ModListAuthor = ChangedProperties ? this.Slideshow.SplashScreenAuthorName : null,
ModListDescription = ChangedProperties ? this.Slideshow.SplashScreenSummary : null,
ModListImage = ChangedProperties ? newImagePath : null,
ModListWebsite = ChangedProperties ? _nexusSiteURL : null,
ModListReadme = ChangedProperties ? readmePath : null

View File

@ -45,12 +45,12 @@ namespace Wabbajack
{
BitmapImage splashScreen = new BitmapImage(new Uri(newBannerFile));
state.newImagePath = newBannerFile;
state.SplashScreenImage = splashScreen;
state.Slideshow.SplashScreenImage = splashScreen;
}
state.SplashScreenModName = ModlistNameProperty.Text;
state.SplashScreenSummary = ModlistDescriptionProperty.Text;
state.SplashScreenAuthorName = ModlistAuthorProperty.Text;
state.Slideshow.SplashScreenModName = ModlistNameProperty.Text;
state.Slideshow.SplashScreenSummary = ModlistDescriptionProperty.Text;
state.Slideshow.SplashScreenAuthorName = ModlistAuthorProperty.Text;
state._nexusSiteURL = ModlistWebsiteProperty.Text;
state.readmePath = ModlistReadmeProperty.Text;

View File

@ -1,8 +1,13 @@
using System;
using ReactiveUI;
using System;
using System.Collections.Generic;
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;
@ -49,12 +54,32 @@ namespace Wabbajack.UI
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 _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 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); }
public IReactiveCommand SlideShowNextItemCommand { get; } = ReactiveCommand.Create(() => { });
public SlideShow(AppState appState)
{
SlideShowElements = NexusApiClient.CachedSlideShow.ToList();
@ -62,6 +87,86 @@ namespace Wabbajack.UI
SlidesQueue = new Queue<Slide>();
_random = new Random();
AppState = appState;
// Apply modlist properties when it changes
this.WhenAny(x => x.AppState.ModList)
.NotNull()
.Subscribe(modList =>
{
this.SplashScreenModName = modList.Name;
this.SplashScreenAuthorName = modList.Author;
this.SplashScreenSummary = 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.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.AppState.LogMsg("Error loading splash image.");
}
}
return this.WabbajackLogo;
})
.ObserveOn(RxApp.MainThreadScheduler)
.StartWith(this.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.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()
@ -100,16 +205,16 @@ namespace Wabbajack.UI
if (!slide.IsNSFW || (slide.IsNSFW && ShowNSFW))
{
AppState.SplashScreenImage = AppState._noneImage;
this.SplashScreenImage = AppState._noneImage;
if (slide.ImageURL != null && slide.Image != null)
{
if (!CachedSlides.ContainsKey(slide.ModID)) return;
AppState.SplashScreenImage = slide.Image;
this.SplashScreenImage = slide.Image;
}
AppState.SplashScreenModName = slide.ModName;
AppState.SplashScreenAuthorName = slide.ModAuthor;
AppState.SplashScreenSummary = slide.ModDescription;
this.SplashScreenModName = slide.ModName;
this.SplashScreenAuthorName = slide.ModAuthor;
this.SplashScreenSummary = slide.ModDescription;
AppState._nexusSiteURL = slide.ModURL;
}

View File

@ -26,7 +26,7 @@
<Image
Grid.Row="0"
Margin="0,0,0,4"
Source="{Binding AppState.SplashScreenImage}"
Source="{Binding SplashScreenImage}"
Stretch="Fill" />
<Button
Grid.Row="1"
@ -50,7 +50,7 @@
</Grid.RowDefinitions>
<Image
Grid.Row="0"
Source="{Binding AppState.SplashScreenImage}"
Source="{Binding SplashScreenImage}"
Stretch="Fill" />
<Button
Grid.Row="1"
@ -80,17 +80,17 @@
Grid.Row="0"
FontSize="30"
FontWeight="Bold"
Text="{Binding AppState.SplashScreenModName}" />
Text="{Binding SplashScreenModName}" />
<TextBlock
Grid.Row="1"
FontSize="15"
FontWeight="Bold"
Text="{Binding AppState.SplashScreenAuthorName}" />
Text="{Binding SplashScreenAuthorName}" />
<TextBlock
Grid.Row="2"
FontSize="15"
FontWeight="Bold"
Text="{Binding AppState.SplashScreenSummary}"
Text="{Binding SplashScreenSummary}"
TextWrapping="Wrap" />
<Grid Grid.Row="3" VerticalAlignment="Bottom">
<Grid.ColumnDefinitions>
@ -102,24 +102,24 @@
Name="EnableSlideShow"
Grid.Column="0"
Margin="0,10,0,0"
IsChecked="{Binding AppState.EnableSlideShow}">
IsChecked="{Binding EnableSlideShow}">
Enable the Slideshow
</CheckBox>
<CheckBox
Name="ShowNSFWContent"
Grid.Column="1"
Margin="4,10,0,0"
IsChecked="{Binding AppState.SplashShowNSFW}">
IsChecked="{Binding SplashShowNSFW}">
Show NSFW Mods in the Slideshow
</CheckBox>
<Button
Grid.Column="2"
Height="30"
HorizontalAlignment="Right"
Command="{Binding AppState.SlideShowNextItemCommand}"
Command="{Binding SlideShowNextItemCommand}"
ToolTip="Skip to next slide">
<DockPanel>
<Image Source="{Binding AppState.NextIcon}" Stretch="Fill" />
<Image Source="{Binding NextIcon}" Stretch="Fill" />
</DockPanel>
</Button>
</Grid>