Merge pull request #115 from Noggog/slide-show-timing

Slide show timing
This commit is contained in:
Timothy Baldridge 2019-10-23 18:53:03 -06:00 committed by GitHub
commit 1195e3b640
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 8 deletions

View File

@ -1,5 +1,10 @@
### Changelog
#### Unreleased changes
* Nothing yet...
* Slideshow more responsive on pressing next
* Slideshow timer resets when next is pressed
#### Version 1.0 alpha 2 - 10/15/2019
* Fix installer running in wrong mode

View File

@ -2,6 +2,8 @@
using System.Linq;
using System.Linq.Expressions;
using System.Reactive;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using DynamicData;
using DynamicData.Kernel;
@ -92,6 +94,63 @@ namespace Wabbajack
.Unit();
}
/// Inspiration:
/// http://reactivex.io/documentation/operators/debounce.html
/// https://stackoverflow.com/questions/20034476/how-can-i-use-reactive-extensions-to-throttle-events-using-a-max-window-size
public static IObservable<T> Debounce<T>(this IObservable<T> source, TimeSpan interval, IScheduler scheduler = null)
{
scheduler = scheduler ?? Scheduler.Default;
return Observable.Create<T>(o =>
{
var hasValue = false;
bool throttling = false;
T value = default;
var dueTimeDisposable = new SerialDisposable();
void internalCallback()
{
if (hasValue)
{
// We have another value that came in to fire.
// Reregister for callback
dueTimeDisposable.Disposable = scheduler.Schedule(interval, internalCallback);
o.OnNext(value);
value = default;
hasValue = false;
}
else
{
// Nothing to do, throttle is complete.
throttling = false;
}
}
return source.Subscribe(
onNext: (x) =>
{
if (!throttling)
{
// Fire initial value
o.OnNext(x);
// Mark that we're throttling
throttling = true;
// Register for callback when throttle is complete
dueTimeDisposable.Disposable = scheduler.Schedule(interval, internalCallback);
}
else
{
// In the middle of throttle
// Save value and return
hasValue = true;
value = x;
}
},
onError: o.OnError,
onCompleted: o.OnCompleted);
});
}
/// 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

View File

@ -137,13 +137,22 @@ namespace Wabbajack
.DisposeWith(this.CompositeDisposable);
/// Wire slideshow updates
// Merge all the sources that trigger a slideshow update
var intervalSeconds = 10;
// Compile 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
this.SlideShowNextItemCommand.StartingExecution(),
// If the natural timer fires
Observable.Merge(
// Start with an initial timer
Observable.Return(Observable.Interval(TimeSpan.FromSeconds(intervalSeconds))),
// but reset timer if user requests one
this.SlideShowNextItemCommand.StartingExecution()
.Select(_ => Observable.Interval(TimeSpan.FromSeconds(intervalSeconds))))
// When a new timer comes in, swap to it
.Switch()
.Unit())
// When filter switch enabled, fire an initial signal
.StartWith(Unit.Default)
// Only subscribe to slideshow triggers if enabled and installing
.FilterSwitch(
@ -151,8 +160,8 @@ namespace Wabbajack
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)
// Don't ever update more than once every half second.
.Debounce(TimeSpan.FromMilliseconds(500), RxApp.MainThreadScheduler)
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(_ => this.UpdateSlideShowItem())
.DisposeWith(this.CompositeDisposable);
@ -261,7 +270,7 @@ namespace Wabbajack
var idx = _random.Next(0, SlideShowElements.Count);
var element = SlideShowElements[idx];
if (checkLast)
if (checkLast && SlideShowElements.Count > 1)
{
while (element == _lastSlide && (!element.IsNSFW || (element.IsNSFW && ShowNSFW)))
{