Skip to content

Commit

Permalink
Live TMP
Browse files Browse the repository at this point in the history
  • Loading branch information
tareqimbasher committed Jan 1, 2024
1 parent 94e392b commit 995a8d3
Show file tree
Hide file tree
Showing 10 changed files with 729 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,24 @@ export abstract class OutputViewBase extends ViewModelBase {
// Replace the previous script
group.lastElementChild.remove();
group.appendChild(script);
} else if (group.getAttribute("tag")?.startsWith("live-collection")) {
const liveCollectionId = group.getAttribute("tag")!.split(':')[1];
const existingLiveCollectionGroup =
batch.find((item, index) => index < iEl && item.getAttribute("id") == liveCollectionId) ??
document.getElementById(liveCollectionId);

if (existingLiveCollectionGroup) {
const incomingTable = group.lastElementChild as HTMLTableElement;

const table = existingLiveCollectionGroup.lastElementChild as HTMLTableElement;
table.replaceWith(incomingTable);

// table.tBodies.item(0)!.innerHTML = incomingTable.tBodies.item(0)!.innerHTML;

// We don't need this group anymore, remove it.
batch.splice(iEl, 1);
iEl--;
}
}
}

Expand Down
124 changes: 124 additions & 0 deletions src/Core/NetPad.Presentation/CollectionChangeNotifier.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;

namespace NetPad;

public enum CollectionChangeType
{
CollectionLevelChange, ItemLevelChange
}

public delegate void CollectionChangeHandler();

public class CollectionChangeNotifier<TItem>
{
private readonly bool _collectionItemsNotifyOnPropertyChange;
private readonly ObservableCollection<TItem>? _observableCollection;
private readonly CollectionChangeHandler _changeHandler;
private readonly IEnumerable<TItem>? _collection;
private readonly int? _pollMs;
private bool _shouldSendNotifications;

public CollectionChangeNotifier(IEnumerable<TItem> collection, int pollMs, CollectionChangeHandler changeHandler) : this(changeHandler)
{
_collection = collection;
_pollMs = pollMs;
}

public CollectionChangeNotifier(ObservableCollection<TItem> observableCollection, CollectionChangeHandler changeHandler) : this(changeHandler)
{
_observableCollection = observableCollection;
}

private CollectionChangeNotifier(CollectionChangeHandler changeHandler)
{
_changeHandler = changeHandler;

_collectionItemsNotifyOnPropertyChange = typeof(INotifyPropertyChanged).IsAssignableFrom(typeof(TItem));
}

public async void StartChangeNotifications()
{
_shouldSendNotifications = true;

if (_observableCollection != null)
{
_observableCollection.CollectionChanged += OnObservableCollectionChanged;
}
else if (_collection != null && _pollMs.HasValue)
{
while (_shouldSendNotifications)
{
_changeHandler();
await Task.Delay(_pollMs.Value);
}
}
else
{
throw new Exception("Invalid state. Both collections are null.");
}

if (_collectionItemsNotifyOnPropertyChange)
{
foreach (INotifyPropertyChanged item in (_observableCollection ?? _collection!))
{
if (item != null)
{
item.PropertyChanged += ItemPropertyChanged;
}
}
}
}

public void StopChangeNotifications()
{
_shouldSendNotifications = false;

if (_observableCollection != null)
{
_observableCollection.CollectionChanged -= OnObservableCollectionChanged;
}

if (_collectionItemsNotifyOnPropertyChange)
{
foreach (INotifyPropertyChanged item in (_observableCollection ?? _collection!))
{
if (item != null)
{
item.PropertyChanged -= ItemPropertyChanged;
}
}
}
}

private void OnObservableCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (_collectionItemsNotifyOnPropertyChange)
{
if (e.NewItems != null)
{
foreach (INotifyPropertyChanged item in e.NewItems)
{
item.PropertyChanged += ItemPropertyChanged;
}
}

if (e.OldItems != null)
{
foreach (INotifyPropertyChanged item in e.OldItems)
{
item.PropertyChanged -= ItemPropertyChanged;
}
}
}

_changeHandler();
}

private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// NotifyCollectionChangedEventArgs args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, sender, sender, IndexOf((T)sender));
_changeHandler();
}
}
133 changes: 133 additions & 0 deletions src/Core/NetPad.Presentation/CollectionPresentationView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
using System.Collections.ObjectModel;

namespace NetPad;

public class CollectionPresentationView<T> : PresentationView<IEnumerable<T>>
{
private readonly CollectionChangeNotifier<T> _collectionChangeNotifier;

public CollectionPresentationView(IEnumerable<T> seed, int pollMs) : base(seed)
{
_collectionChangeNotifier = new CollectionChangeNotifier<T>(seed, pollMs, () => { DebouncedFlush(); });
}

public CollectionPresentationView(ObservableCollection<T> seed) : base(seed)
{
_collectionChangeNotifier = new CollectionChangeNotifier<T>(seed, () => { DebouncedFlush(); });
}

public int Length { get; private set; }

public override void StartLiveView(Action<IEnumerable<T>> outputWriter, Func<bool>? stopWhen = null, CancellationToken cancellationToken = default)
{
base.StartLiveView(outputWriter, stopWhen, cancellationToken);

_collectionChangeNotifier.StartChangeNotifications();
}

public override void StopLiveView()
{
base.StopLiveView();

_collectionChangeNotifier.StopChangeNotifications();
}

private T[]? _lastView;

public override void UpdateView(IEnumerable<T> data, bool force = false)
{
var items = Data.ToArray();

// if (_lastView != null && items.SequenceEqual(_lastView))
// {
// return;
// }
//
// _lastView = items;

Length = items.Length;

base.UpdateView(items);
}


/// <summary>
/// Filters this view by the provided predicate. This alters the view "in-place".
/// </summary>
public CollectionPresentationView<T> Where(Func<T, bool> predicate)
{
Data = Data.Where(predicate);
DebouncedFlush();
return this;
}

public CollectionPresentationView<T> Skip(int count)
{
Data = Data.Skip(count);
DebouncedFlush();
return this;
}

public CollectionPresentationView<T> Take(int count)
{
Data = Data.Take(count);
DebouncedFlush();
return this;
}

public CollectionPresentationView<T> Take(Range range)
{
Data = Data.Take(range);
DebouncedFlush();
return this;
}

public CollectionPresentationView<T> OrderBy<TKey>(Func<T, TKey> keySelector)
{
Data = Data.OrderBy(keySelector);
DebouncedFlush();
return this;
}

public CollectionPresentationView<T> OrderByDescending<TKey>(Func<T, TKey> keySelector)
{
Data = Data.OrderByDescending(keySelector);
DebouncedFlush();
return this;
}

public CollectionPresentationView<T> DistinctBy<TKey>(Func<T, TKey> keySelector)
{
Data = Data.DistinctBy(keySelector);
DebouncedFlush();
return this;
}

public CollectionPresentationView<T> UnionBy<TKey>(Func<T, TKey> keySelector, IEnumerable<T> second)
{
Data = Data.UnionBy(second, keySelector);
DebouncedFlush();
return this;
}

public CollectionPresentationView<T> ExceptBy<TKey>(Func<T, TKey> keySelector, IEnumerable<TKey> second)
{
Data = Data.ExceptBy(second, keySelector);
DebouncedFlush();
return this;
}

public CollectionPresentationView<T> IntersectBy<TKey>(Func<T, TKey> keySelector, IEnumerable<TKey> second)
{
Data = Data.IntersectBy(second, keySelector);
DebouncedFlush();
return this;
}

public CollectionPresentationView<T> Concat(IEnumerable<T> second)
{
Data = Data.Concat(second);
DebouncedFlush();
return this;
}
}
Loading

0 comments on commit 995a8d3

Please sign in to comment.