diff --git a/playground/Playground.cs b/playground/Playground.cs index 61cb373..ddd23c5 100644 --- a/playground/Playground.cs +++ b/playground/Playground.cs @@ -5,31 +5,29 @@ class Playground { - static async Task Main() + class MutableObject + { + public string Field = "initial"; + } + + static void Main() { - var stateA = Observable.State("hello"); - var stateB = Observable.State("world"); + var mutableObject = new MutableObject(); - var o = Observable.Auto(async () => - { - Console.WriteLine("computing"); - var a = stateA.Value; - await Task.Delay(1000); - var b = stateB.Value; - return a + " " + b; - }); + var mutableObjectSource = Observable.Manual(mutableObject); - o.Bind(result => Console.WriteLine(result.Status switch - { - AsyncComputeStatus.Loading => "Loading...", - AsyncComputeStatus.Done => "Done: " + result.Result, - AsyncComputeStatus.Failed => "Failed: " + result.Exception, - })); + void Mutate(string newFieldValue) + { + mutableObject.Field = newFieldValue; + mutableObjectSource.Invalidate(); + } - await Task.Delay(1500); + var mutableObjectObservable = mutableObjectSource.Observe(); + mutableObjectObservable.Bind(o => Console.WriteLine(o.Field)); - stateB.Value = "Dan"; + var auto = Observable.Auto(() => mutableObjectObservable.Value.Field.ToUpperInvariant()); + auto.Bind(v => Console.WriteLine(v)); - Process.GetCurrentProcess().WaitForExit(); + Mutate("Hello"); } } diff --git a/src/TinkState/Runtime/Internal/ManualObservableSource.cs b/src/TinkState/Runtime/Internal/ManualObservableSource.cs new file mode 100644 index 0000000..3e8fefb --- /dev/null +++ b/src/TinkState/Runtime/Internal/ManualObservableSource.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; + +namespace TinkState.Internal +{ + class ManualObservableSource : Dispatcher, Observable, TinkState.ManualObservableSource, DispatchingObservable + { + T value; + + public ManualObservableSource(T initialValue) + { + value = initialValue; + } + + public T Value => AutoObservable.Track(this); + + public Observable Observe() + { + return this; + } + + public void Invalidate() + { + Fire(); + } + + public void Update(T newValue) + { + value = newValue; + Fire(); + } + + public IDisposable Bind(Action callback, IEqualityComparer comparer = null, Scheduler scheduler = null) + { + return new Binding(this, callback, comparer, scheduler); + } + + public Observable Map(Func transform, IEqualityComparer comparer = null) + { + return new TransformObservable(this, transform, comparer); + } + + public IEqualityComparer GetComparer() + { + return NeverEqualityComparer.Instance; + } + + public long GetRevision() + { + return revision; + } + + public T GetCurrentValue() + { + return value; + } + } +} \ No newline at end of file diff --git a/src/TinkState/Runtime/ManualObservableSource.cs b/src/TinkState/Runtime/ManualObservableSource.cs new file mode 100644 index 0000000..012ed68 --- /dev/null +++ b/src/TinkState/Runtime/ManualObservableSource.cs @@ -0,0 +1,9 @@ +namespace TinkState +{ + public interface ManualObservableSource + { + Observable Observe(); + void Invalidate(); + void Update(T newValue); + } +} \ No newline at end of file diff --git a/src/TinkState/Runtime/Observable.cs b/src/TinkState/Runtime/Observable.cs index 36fb641..b763e14 100644 --- a/src/TinkState/Runtime/Observable.cs +++ b/src/TinkState/Runtime/Observable.cs @@ -212,6 +212,11 @@ public static ObservableDictionary Dictionary() // TODO: Dictionary with initial value + public static ManualObservableSource Manual(T initialValue) + { + return new Internal.ManualObservableSource(initialValue); + } + /// /// Default scheduler used for bindings. ///