From 6714c582d0ccb5e314ab2581adddf500d1370053 Mon Sep 17 00:00:00 2001 From: desmaisons_david Date: Sat, 16 Feb 2019 02:10:57 -0200 Subject: [PATCH] Support range replace upadtes part of issue #105 --- Neutronium.Core/Binding/GlueObject/JSArray.cs | 40 +++++++++++++++---- .../Updaters/CollectionJavascriptUpdater.cs | 28 ++++++++----- .../HTMLBindingTests_Collection.cs | 27 +++++++++++++ docs/manifest.json | 8 ++-- 4 files changed, 80 insertions(+), 23 deletions(-) diff --git a/Neutronium.Core/Binding/GlueObject/JSArray.cs b/Neutronium.Core/Binding/GlueObject/JSArray.cs index ed064db1..5fad0fc6 100644 --- a/Neutronium.Core/Binding/GlueObject/JSArray.cs +++ b/Neutronium.Core/Binding/GlueObject/JSArray.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections; -using System.Collections.Generic; +using MoreCollection.Extensions; +using Neutronium.Core.Binding.Builder; using Neutronium.Core.Binding.CollectionChanges; +using Neutronium.Core.Binding.Listeners; using Neutronium.Core.JavascriptFramework; using Neutronium.Core.WebBrowserEngine.JavascriptObject; -using MoreCollection.Extensions; -using Neutronium.Core.Binding.Builder; -using Neutronium.Core.Binding.Listeners; +using System; +using System.Collections; +using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; @@ -26,7 +26,7 @@ internal class JsArray : GlueBase, IJsCsCachableGlue public JsArray(IEnumerable collection, Type individual) { - CValue = collection; + CValue = collection; _IndividualType = individual; } @@ -46,7 +46,7 @@ public void VisitDescendants(Func visit) } } - public void VisitChildren(Action visit) + public void VisitChildren(Action visit) { foreach (var item in Items) visit(item); @@ -131,6 +131,16 @@ private static BridgeUpdater CheckForRemove(BridgeUpdater updater, IJsCsGlue glu return updater; } + private static BridgeUpdater CheckForRemove(BridgeUpdater updater, List glues) + { + glues.ForEach(glue => + { + if (glue.Release()) + updater.Remove(glue); + }); + return updater; + } + public BridgeUpdater GetReplaceUpdater(IJsCsGlue glue, int index) { var bridgeUpdater = new BridgeUpdater(viewModelUpdater => Splice(viewModelUpdater, index, 1, glue)); @@ -139,6 +149,20 @@ public BridgeUpdater GetReplaceUpdater(IJsCsGlue glue, int index) return CheckForRemove(bridgeUpdater, old); } + public BridgeUpdater GetReplaceUpdater(List glues, int index) + { + var bridgeUpdater = new BridgeUpdater(viewModelUpdater => Splice(viewModelUpdater, index, glues.Count, glues)); + + var oldChildren = new List(); + glues.ForEach(glue => + { + var old = Items[index]; + Items[index] = glue.AddRef(); + oldChildren.Add(old); + }); + return CheckForRemove(bridgeUpdater, oldChildren); + } + public BridgeUpdater GetMoveUpdater(int oldIndex, int newIndex) { var item = Items[oldIndex]; diff --git a/Neutronium.Core/Binding/Updaters/CollectionJavascriptUpdater.cs b/Neutronium.Core/Binding/Updaters/CollectionJavascriptUpdater.cs index 08ba79da..fb45bb55 100644 --- a/Neutronium.Core/Binding/Updaters/CollectionJavascriptUpdater.cs +++ b/Neutronium.Core/Binding/Updaters/CollectionJavascriptUpdater.cs @@ -42,11 +42,7 @@ private BridgeUpdater GetBridgeUpdater(JsArray array) return GetAddUpdater(array); case NotifyCollectionChangedAction.Replace: - var newValue = _JsUpdateHelper.Map(_Change.NewItems[0]); - if (newValue == null) - return null; - NewJsValues.Add(newValue); - return array.GetReplaceUpdater(newValue, _Change.NewStartingIndex); + return GetReplaceUpdater(array); case NotifyCollectionChangedAction.Remove: return array.GetRemoveUpdater(_Change.OldStartingIndex, _Change.OldItems.Count); @@ -64,18 +60,28 @@ private BridgeUpdater GetBridgeUpdater(JsArray array) private BridgeUpdater GetAddUpdater(JsArray array) { + InitValuesFromNewItems(); if (_Change.NewItems.Count == 1) { - var newValue = _JsUpdateHelper.Map(_Change.NewItems[0]); - if (newValue == null) - return null; - NewJsValues.Add(newValue); - return array.GetAddUpdater(newValue, _Change.NewStartingIndex); + return array.GetAddUpdater(_NewJsValues[0], _Change.NewStartingIndex); } + return array.GetAddUpdater(_NewJsValues, _Change.NewStartingIndex); + } + private BridgeUpdater GetReplaceUpdater(JsArray array) + { + InitValuesFromNewItems(); + if (_Change.NewItems.Count == 1) + { + return array.GetReplaceUpdater(_NewJsValues[0], _Change.NewStartingIndex); + } + return array.GetReplaceUpdater(_NewJsValues, _Change.NewStartingIndex); + } + + private void InitValuesFromNewItems() + { _NewJsValues = _Change.NewItems.Cast().Select(item => _JsUpdateHelper.Map(item)) .ToList(); - return array.GetAddUpdater(_NewJsValues, _Change.NewStartingIndex); } public void OnJsContext() diff --git a/Tests/UniversalTests/HTMLBindingTests/HTMLBindingTests_Collection.cs b/Tests/UniversalTests/HTMLBindingTests/HTMLBindingTests_Collection.cs index 6a219f53..cc88271a 100644 --- a/Tests/UniversalTests/HTMLBindingTests/HTMLBindingTests_Collection.cs +++ b/Tests/UniversalTests/HTMLBindingTests/HTMLBindingTests_Collection.cs @@ -228,6 +228,33 @@ public async Task TwoWay_Collection_Updates_After_RemoveRange_Changes() await RunAsync(test); } + [Fact] + public async Task TwoWay_Collection_Updates_After_ReplaceRange_Changes() + { + var dataContext = new VmWithRangeCollection(); + dataContext.List.AddRange(new[] { 1, 20, 30, 40, 5 }); + var test = new TestInContextAsync() + { + Bind = (win) => HtmlBinding.Bind(win, dataContext, JavascriptBindingMode.TwoWay), + Test = async (mb) => + { + var js = mb.JsRootObject; + + DoSafeUI(() => + { + dataContext.List.ReplaceRange(1, 3, new[] { 2, 3, 4 }); + }); + + await Task.Delay(500); + var col = GetCollectionAttribute(js, "List"); + col.Should().NotBeNull(); + CheckIntCollection(col, new[] { 1, 2, 3, 4, 5 }); + } + }; + + await RunAsync(test); + } + [Fact] public async Task TwoWay_Collection_Updates_CSharp_From_JS_Update() { diff --git a/docs/manifest.json b/docs/manifest.json index 11637ace..454650be 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1067,18 +1067,18 @@ "incrementalPhase": "build" }, "processors": { - "TocDocumentProcessor": { + "ResourceDocumentProcessor": { "can_incremental": false, - "details": "Processor TocDocumentProcessor cannot support incremental build because the processor doesn't implement ISupportIncrementalDocumentProcessor interface.", + "details": "Processor ResourceDocumentProcessor cannot support incremental build because the processor doesn't implement ISupportIncrementalDocumentProcessor interface.", "incrementalPhase": "build" }, "ConceptualDocumentProcessor": { "can_incremental": false, "incrementalPhase": "build" }, - "ResourceDocumentProcessor": { + "TocDocumentProcessor": { "can_incremental": false, - "details": "Processor ResourceDocumentProcessor cannot support incremental build because the processor doesn't implement ISupportIncrementalDocumentProcessor interface.", + "details": "Processor TocDocumentProcessor cannot support incremental build because the processor doesn't implement ISupportIncrementalDocumentProcessor interface.", "incrementalPhase": "build" } }