mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Slideshow update thread removed in favor of Rx
Will want to replace the throttle /w a debounce call. Also will want to remove unnecessary subject once command IsExecuting callbacks are researched
This commit is contained in:
parent
c808f9a4ed
commit
ff2010134c
@ -22,18 +22,17 @@ using Wabbajack.NexusApi;
|
||||
using Wabbajack.UI;
|
||||
using DynamicData;
|
||||
using DynamicData.Binding;
|
||||
using System.Reactive;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
public enum TaskMode { INSTALLING, BUILDING }
|
||||
internal class AppState : ViewModel, IDataErrorInfo
|
||||
public class AppState : ViewModel, IDataErrorInfo
|
||||
{
|
||||
public const bool GcCollect = true;
|
||||
|
||||
private SlideShow _slideShow;
|
||||
|
||||
public bool installing = false;
|
||||
|
||||
private string _mo2Folder;
|
||||
|
||||
private readonly BitmapImage _wabbajackLogo = UIUtils.BitmapImageFromResource("Wabbajack.UI.banner.png");
|
||||
@ -59,7 +58,7 @@ namespace Wabbajack
|
||||
|
||||
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); }
|
||||
|
||||
@ -69,6 +68,9 @@ namespace Wabbajack
|
||||
private string _HTMLReport;
|
||||
public string HTMLReport { get => _HTMLReport; set => this.RaiseAndSetIfChanged(ref _HTMLReport, value); }
|
||||
|
||||
private bool _Installing;
|
||||
public bool Installing { get => _Installing; set => this.RaiseAndSetIfChanged(ref _Installing, value); }
|
||||
|
||||
// Command properties
|
||||
public IReactiveCommand ChangePathCommand => ReactiveCommand.Create(ExecuteChangePath);
|
||||
public IReactiveCommand ChangeDownloadPathCommand => ReactiveCommand.Create(ExecuteChangeDownloadPath);
|
||||
@ -77,7 +79,10 @@ namespace Wabbajack
|
||||
public IReactiveCommand VisitNexusSiteCommand => ReactiveCommand.Create(VisitNexusSite);
|
||||
public IReactiveCommand OpenReadmeCommand { get; }
|
||||
public IReactiveCommand OpenModListPropertiesCommand => ReactiveCommand.Create(OpenModListProperties);
|
||||
public IReactiveCommand SlideShowNextItemCommand { get; }
|
||||
// ToDo
|
||||
// This subject is not desirable. Need to research why command's IsExecuting observable not firing, as we'd prefer to hook onto that instead
|
||||
private Subject<Unit> _slideshowCommandTriggeredSubject = new Subject<Unit>();
|
||||
public ReactiveCommand<Unit, Unit> SlideShowNextItemCommand => ReactiveCommand.Create(() => _slideshowCommandTriggeredSubject.OnNext(Unit.Default));
|
||||
|
||||
public AppState()
|
||||
{
|
||||
@ -121,7 +126,6 @@ namespace Wabbajack
|
||||
.DisposeWith(this.CompositeDisposable);
|
||||
|
||||
_slideShow = new SlideShow(this, true);
|
||||
this.SlideShowNextItemCommand = ReactiveCommand.Create(_slideShow.UpdateSlideShowItem);
|
||||
|
||||
// Update splashscreen when modlist changes
|
||||
Observable.CombineLatest(
|
||||
@ -170,10 +174,24 @@ namespace Wabbajack
|
||||
.Subscribe(bitmap => this.SplashScreenImage = bitmap)
|
||||
.DisposeWith(this.CompositeDisposable);
|
||||
|
||||
// Trigger a slideshow update if enabled
|
||||
this.WhenAny(x => x.EnableSlideShow)
|
||||
.Skip(1) // Don't fire initially
|
||||
.WhenAny(enable => enable)
|
||||
/// 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
|
||||
_slideshowCommandTriggeredSubject)
|
||||
// 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);
|
||||
|
||||
@ -192,17 +210,8 @@ namespace Wabbajack
|
||||
.Bind(this.Status)
|
||||
.Subscribe()
|
||||
.DisposeWith(this.CompositeDisposable);
|
||||
|
||||
slideshowThread = new Thread(UpdateLoop)
|
||||
{
|
||||
Priority = ThreadPriority.BelowNormal,
|
||||
IsBackground = true
|
||||
};
|
||||
slideshowThread.Start();
|
||||
}
|
||||
|
||||
public DateTime lastSlideShowUpdate = new DateTime();
|
||||
|
||||
public ObservableCollection<string> Log { get; } = new ObservableCollection<string>();
|
||||
|
||||
private string _Location;
|
||||
@ -316,8 +325,7 @@ namespace Wabbajack
|
||||
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); }
|
||||
private readonly Thread slideshowThread = null;
|
||||
public bool SplashShowNSFW { get => _splashShowNSFW; set => this.RaiseAndSetIfChanged(ref _splashShowNSFW, value); }
|
||||
|
||||
public string Error => "Error";
|
||||
|
||||
@ -355,23 +363,6 @@ namespace Wabbajack
|
||||
return validationMessage;
|
||||
}
|
||||
|
||||
private void UpdateLoop()
|
||||
{
|
||||
while (Running)
|
||||
{
|
||||
if (_slideShow.SlidesQueue.Any())
|
||||
{
|
||||
if (DateTime.Now - lastSlideShowUpdate > TimeSpan.FromSeconds(10))
|
||||
{
|
||||
_slideShow.UpdateSlideShowItem();
|
||||
}
|
||||
}
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Running { get; set; } = true;
|
||||
|
||||
public void LogMsg(string msg)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() => Log.Add(msg));
|
||||
@ -425,7 +416,7 @@ namespace Wabbajack
|
||||
UIReady = false;
|
||||
if (Mode == TaskMode.INSTALLING)
|
||||
{
|
||||
installing = true;
|
||||
this.Installing = true;
|
||||
var installer = new Installer(this.ModListPath, this.ModList, Location)
|
||||
{
|
||||
DownloadFolder = DownloadLocation
|
||||
@ -447,9 +438,7 @@ namespace Wabbajack
|
||||
finally
|
||||
{
|
||||
UIReady = true;
|
||||
Running = false;
|
||||
installing = false;
|
||||
slideshowThread.Abort();
|
||||
this.Installing = false;
|
||||
}
|
||||
})
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using DynamicData;
|
||||
using DynamicData.Kernel;
|
||||
@ -29,6 +30,38 @@ namespace Wabbajack
|
||||
return source.ObserveOn(RxApp.MainThreadScheduler);
|
||||
}
|
||||
|
||||
public static IObservable<Unit> Unit<T>(this IObservable<T> source)
|
||||
{
|
||||
return source.Select(_ => System.Reactive.Unit.Default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience operator to subscribe to the source observable, only when a second "switch" observable is on.
|
||||
/// When the switch is on, the source will be subscribed to, and its updates passed through.
|
||||
/// When the switch is off, the subscription to the source observable will be stopped, and no signal will be published.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source">Source observable to subscribe to if on</param>
|
||||
/// <param name="filterSwitch">On/Off signal of whether to subscribe to source observable</param>
|
||||
/// <returns>Observable that publishes data from source, if the switch is on.</returns>
|
||||
public static IObservable<T> FilterSwitch<T>(this IObservable<T> source, IObservable<bool> filterSwitch)
|
||||
{
|
||||
return filterSwitch
|
||||
.DistinctUntilChanged()
|
||||
.Select(on =>
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
return source;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Observable.Empty<T>();
|
||||
}
|
||||
})
|
||||
.Switch();
|
||||
}
|
||||
|
||||
/// These snippets were provided by RolandPheasant (author of DynamicData)
|
||||
/// They'll be going into the official library at some point, but are here for now.
|
||||
#region Dynamic Data EnsureUniqueChanges
|
||||
|
@ -149,7 +149,7 @@
|
||||
Height="30"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding SlideShowNextItemCommand}"
|
||||
ToolTip="Spamming this button will result in problems">
|
||||
ToolTip="Skip to next slide">
|
||||
<DockPanel>
|
||||
<Image Source="{Binding NextIcon}" Stretch="Fill" />
|
||||
</DockPanel>
|
||||
|
@ -68,7 +68,6 @@ namespace Wabbajack
|
||||
MessageBoxImage.Error);
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
context.Running = false;
|
||||
ExitWhenClosing = false;
|
||||
var window = new ModeSelectionWindow
|
||||
{
|
||||
|
@ -74,7 +74,7 @@ namespace Wabbajack.UI
|
||||
|
||||
public void UpdateSlideShowItem()
|
||||
{
|
||||
if (!_appState.EnableSlideShow || !_appState.installing || SlidesQueue.Count==0) return;
|
||||
if (SlidesQueue.Count == 0) return;
|
||||
var slide = SlidesQueue.Peek();
|
||||
|
||||
while (CachedSlides.Count >= MaxCacheSize)
|
||||
@ -98,11 +98,8 @@ namespace Wabbajack.UI
|
||||
_appState.SplashScreenImage = _appState._noneImage;
|
||||
if (slide.ImageURL != null && slide.Image != null)
|
||||
{
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (!CachedSlides.ContainsKey(slide.ModID)) return;
|
||||
_appState.SplashScreenImage = slide.Image;
|
||||
});
|
||||
if (!CachedSlides.ContainsKey(slide.ModID)) return;
|
||||
_appState.SplashScreenImage = slide.Image;
|
||||
}
|
||||
|
||||
_appState.SplashScreenModName = slide.ModName;
|
||||
@ -111,8 +108,6 @@ namespace Wabbajack.UI
|
||||
_appState._nexusSiteURL = slide.ModURL;
|
||||
}
|
||||
|
||||
_appState.lastSlideShowUpdate = DateTime.Now;
|
||||
|
||||
SlidesQueue.Dequeue();
|
||||
QueueRandomSlide(false, true);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user