From 0273c08f2306b3268c33e78a06ea2539f52a17f3 Mon Sep 17 00:00:00 2001 From: Tianer Zhou Date: Wed, 19 Feb 2025 17:14:11 +0800 Subject: [PATCH] handle LazyForEach hybrid scenario Signed-off-by: Tianer Zhou --- arkoala-arkts/arkui/src/LazyForEach.ts | 48 +++++++++++++++++-- arkoala-arkts/arkui/src/generated/PeerNode.ts | 1 + 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/arkoala-arkts/arkui/src/LazyForEach.ts b/arkoala-arkts/arkui/src/LazyForEach.ts index 3acd403c2..d07b1b456 100644 --- a/arkoala-arkts/arkui/src/LazyForEach.ts +++ b/arkoala-arkts/arkui/src/LazyForEach.ts @@ -13,10 +13,10 @@ * limitations under the License. */ -import { __context, contextNode, memoEntry2, remember, rememberMutableState, scheduleCallback } from "@koalaui/runtime" -import { hashCodeFromString, int32 } from "@koalaui/common" +import { __context, __id, contextNode, DataNode, IncrementalNode, memoEntry2, remember, rememberMutableState, scheduleCallback } from "@koalaui/runtime" +import { hashCodeFromString, int32, KoalaCallsiteKey } from "@koalaui/common" import { nullptr, pointer } from "@koalaui/interop"; -import { PeerNode } from "./generated/PeerNode"; +import { LazyForEachType, PeerNode, PeerNodeType } from "./generated/PeerNode"; import { LazyForEachOps } from "./generated/ArkLazyForEachOpsMaterialized" // TODO: proper import [DataChangeListener] from lazy_for_each.d.ts @@ -109,6 +109,40 @@ class VisibleRange { } } +class LazyForEachIdentifier { + constructor(id: KoalaCallsiteKey, totalCnt: int32, activeCnt: int32) { + this.id = id + this.totalCnt = totalCnt + this.activeCnt = activeCnt + } + readonly id: KoalaCallsiteKey + readonly totalCnt: int32 + readonly activeCnt: int32 +} + +/** + * @param id unique identifier of LazyForEach + * @returns item offset of LazyForEach in parent's children + */ +/** @memo */ +function getOffset(parent: PeerNode, id: KoalaCallsiteKey): int32 { + let offset = 0 + for (let child = parent.firstChild; child; child = child!.nextSibling) { + // corresponding DataNode is attached after the generated items + let info = DataNode.extract(LazyForEachType, child!!) + if (info?.id === id) { + offset -= info!.activeCnt + console.log(`offset = ${offset}`) + return offset + } else if (info) { + offset += info!.totalCnt - info!.activeCnt // active nodes are already counted + } else if (child.isKind(PeerNodeType)) { + ++offset + } + } + throw Error(`key not found ${id}`) +} + /** @memo */ export function LazyForEach(dataSource: IDataSource, /** @memo */ @@ -121,7 +155,9 @@ export function LazyForEach(dataSource: IDataSource, console.log(`LazyForEach current=${current.value} version=${version.value} mark=${mark.value}`) let parent = contextNode() - const visibleRange = new VisibleRange(parent, current.value, current.value) + + const currentLocal = current.value - getOffset(parent, __id()); // translated to local index + const visibleRange = new VisibleRange(parent, currentLocal, currentLocal) remember(() => { LazyForEachManager.OnRangeUpdate(visibleRange.parent, dataSource.totalCount() as int32, (currentIndex: int32, currentMark: pointer, end: int32) => { console.log(`LazyForEach[${parent}]: current updated to ${currentIndex} ${currentMark} end=${end}`) @@ -161,4 +197,8 @@ export function LazyForEach(dataSource: IDataSource, LazyForEachManager.SetInsertMark(parent, moreUp ? visibleRange.markUp : visibleRange.markDown, moreUp) } parent.setInsertMark(nullptr, false) + + // create DataNode to provide count information to parent + const activeCnt = visibleRange.indexDown - visibleRange.indexUp + 1 + DataNode.attach(LazyForEachType, new LazyForEachIdentifier(__id(), dataSource.totalCount() as int32, activeCnt)) } diff --git a/arkoala-arkts/arkui/src/generated/PeerNode.ts b/arkoala-arkts/arkui/src/generated/PeerNode.ts index 7a30ef6f0..4702ed7f8 100644 --- a/arkoala-arkts/arkui/src/generated/PeerNode.ts +++ b/arkoala-arkts/arkui/src/generated/PeerNode.ts @@ -5,6 +5,7 @@ import { nullptr, pointer } from "@koalaui/interop" import { ArkRootPeer } from "./peers/ArkStaticComponentsPeer" export const PeerNodeType = 11 +export const LazyForEachType = 13 const InitialID = 999 export class PeerNode extends IncrementalNode { -- Gitee