Fix updates

Signed-off-by: RMidhunSuresh <rmidhunsuresh@gmail.com>
This commit is contained in:
RMidhunSuresh 2021-07-12 13:57:37 +05:30
parent 452eee6767
commit f05574f579

View file

@ -42,6 +42,10 @@ class ItemRange {
totalSize() { totalSize() {
return this.topCount + this.renderCount + this.bottomCount; return this.topCount + this.renderCount + this.bottomCount;
} }
normalize(idx) {
return idx - this.topCount;
}
} }
export class LazyListView extends ListView { export class LazyListView extends ListView {
@ -64,7 +68,7 @@ export class LazyListView extends ListView {
return new ItemRange(topCount, renderCount, bottomCount); return new ItemRange(topCount, renderCount, bottomCount);
} }
_renderMoreIfNeeded() { _renderIfNeeded() {
const range = this._getVisibleRange(); const range = this._getVisibleRange();
const intersectRange = range.expand(this._overflowMargin); const intersectRange = range.expand(this._overflowMargin);
const renderRange = range.expand(this._overflowItems); const renderRange = range.expand(this._overflowItems);
@ -83,6 +87,7 @@ export class LazyListView extends ListView {
} }
_renderItems(items) { _renderItems(items) {
this._childInstances = [];
const fragment = document.createDocumentFragment(); const fragment = document.createDocumentFragment();
for (const item of items) { for (const item of items) {
const view = this._childCreator(item.value); const view = this._childCreator(item.value);
@ -114,8 +119,8 @@ export class LazyListView extends ListView {
But in most of these scroll events, we return early. But in most of these scroll events, we return early.
Do we need to do more (like event throttling)? Do we need to do more (like event throttling)?
*/ */
this._parent.addEventListener("scroll", () => this._renderMoreIfNeeded()); this._parent.addEventListener("scroll", () => this._renderIfNeeded());
this._renderMoreIfNeeded(); this._renderIfNeeded();
return this._parent; return this._parent;
} }
@ -123,49 +128,81 @@ export class LazyListView extends ListView {
if (!this._list) { return; } if (!this._list) { return; }
this._subscription = this._list.subscribe(this); this._subscription = this._list.subscribe(this);
this._childInstances = []; this._childInstances = [];
// todo: this breaks update in parent
} }
// onAdd, onRemove, ... should be called only if the element is already rendered
// If size of the list changes, re-render
onAdd() { onAdd() {
this._renderMoreIfNeeded(); this._renderIfNeeded();
} }
onRemove() { onRemove() {
this._renderMoreIfNeeded(); this._renderIfNeeded();
} }
onUpdate(idx, value, params) { onUpdate(idx, value, params) {
console.log("onUpdate");
if (this._renderRange.containsIndex(idx)) { if (this._renderRange.containsIndex(idx)) {
super.onUpdate(idx, value, params); const normalizedIdx = this._renderRange.normalize(idx);
super.onUpdate(normalizedIdx, value, params);
} }
} }
recreateItem(idx, value) { recreateItem(idx, value) {
console.log("recreateItem");
if (this._renderRange.containsIndex(idx)) { if (this._renderRange.containsIndex(idx)) {
super.recreateItem(idx, value) super.recreateItem(idx, value)
} }
} }
_renderAdditionalElement(fromIdx, toIdx) {
const {topCount, renderCount} = this._renderRange;
const childFromIndex = index => this._childCreator(this._list.get(index));
if (toIdx < fromIdx) {
// Element is moved up the list, so render element from top boundary
const index = topCount;
const child = childFromIndex(index);
// Modify childInstances here
this._root.insertBefore(mountView(child, this._mountArgs), this._root.firstChild);
}
else {
// Element is moved down the list, so render element from bottom boundary
const index = topCount + renderCount - 1;
const child = childFromIndex(index);
this._root.appendChild(mountView(child, this._mountArgs));
}
}
_removeAdditionalElement(fromIdx, toIdx) {
if (toIdx < fromIdx) {
// Element comes from the bottom, so remove element at bottom
this._root.lastChild.remove();
}
else {
this._root.firstChild.remove();
}
}
onMove(fromIdx, toIdx, value) { onMove(fromIdx, toIdx, value) {
console.log("onMove");
const fromInRange = this._renderRange.containsIndex(fromIdx); const fromInRange = this._renderRange.containsIndex(fromIdx);
const toInRange = this._renderRange.containsIndex(toIdx); const toInRange = this._renderRange.containsIndex(toIdx);
const normalizedFromIdx = this._renderRange.normalize(fromIdx);
const normalizedToIdx = this._renderRange.normalize(toIdx);
if (fromInRange && toInRange) { if (fromInRange && toInRange) {
super.onMove(fromIdx, toIdx, value); super.onMove(normalizedFromIdx, normalizedToIdx, value);
} }
else if (fromInRange && !toInRange) { else if (fromInRange && !toInRange) {
this.onBeforeListChanged(); this.onBeforeListChanged();
const [child] = this._childInstances.splice(fromIdx, 1); const [child] = this._childInstances.splice(normalizedFromIdx, 1);
child.root().remove(); child.root().remove();
this._renderAdditionalElement(fromIdx, toIdx);
this.onListChanged(); this.onListChanged();
} }
else if (!fromInRange && toInRange) { else if (!fromInRange && toInRange) {
this.onBeforeListChanged(); this.onBeforeListChanged();
const child = this._childCreator(value); const child = this._childCreator(value);
this._childInstances.splice(toIdx, 0, child); this._childInstances.splice(normalizedToIdx, 0, child);
insertAt(this._root, toIdx, mountView(child, this._mountArgs)); this._removeAdditionalElement(fromIdx, toIdx);
insertAt(this._root, normalizedToIdx, mountView(child, this._mountArgs));
this.onListChanged(); this.onListChanged();
} }
} }