UNPKG

@v4fire/client

Version:

V4Fire client core library

253 lines (213 loc) • 6.72 kB
/*! * V4Fire Client Core * https://github.com/V4Fire/Client * * Released under the MIT license * https://github.com/V4Fire/Client/blob/master/LICENSE */ import Friend from 'super/i-block/modules/friend'; import type bVirtualScrollNew from 'base/b-virtual-scroll-new/b-virtual-scroll-new'; import { isItem } from 'base/b-virtual-scroll-new/modules/helpers'; import { createInitialState, createPrivateInitialState } from 'base/b-virtual-scroll-new/modules/state/helpers'; import type { MountedChild, VirtualScrollState, MountedItem, PrivateComponentState } from 'base/b-virtual-scroll-new/interface'; /** * Friendly to the `bVirtualScroll` class that represents the internal state of a component. */ export class ComponentInternalState extends Friend { override readonly C!: bVirtualScrollNew; /** * Current state of the component. */ protected state: VirtualScrollState = createInitialState(); /** * Current private state of the component. */ protected privateState: PrivateComponentState = createPrivateInitialState(); /** * Compiles and returns the current state of the component. * * @returns The current state of the component. */ compile(): Readonly<VirtualScrollState> { return this.state; } /** * Resets the state of the component */ reset(): void { this.state = createInitialState(); this.privateState = createPrivateInitialState(); } /** * Increments the load page pointer */ incrementLoadPage(): void { this.state.loadPage++; } /** * Increments the render page pointer */ incrementRenderPage(): void { this.state.renderPage++; } /** * Updates the loaded data state. * * @param data - the new data to update the state. * @param isInitialLoading - indicates if it's the initial loading. */ updateData(data: object[], isInitialLoading: boolean): void { this.state.data = this.state.data.concat(data); this.state.isLastEmpty = data.length === 0; this.state.isInitialLoading = isInitialLoading; this.state.lastLoadedData = data; } /** * Updates the arrays with mounted child elements of the component * @param mounted - the mounted child elements. */ updateMounted(mounted: MountedChild[]): void { const {state} = this, childList = <MountedChild[]>state.childList, itemsList = <MountedItem[]>state.items, newItems = <MountedItem[]>mounted.filter((child) => child.type === 'item'); childList.push(...mounted); itemsList.push(...newItems); this.updateRemainingChildren(); } /** * Updates the indicator that shows whether the current rendering process is the * last one in this lifecycle. */ updateIsLastRender(): void { const {state, ctx} = this; if (!state.areRequestsStopped) { return; } const chunkSize = ctx.getChunkSize(state), dataOffset = this.getDataOffset() + chunkSize; if (<CanUndef<object>>state.data[dataOffset] == null) { state.isLastRender = true; } } /** * Updates the state of the last raw loaded data * @param data - the last raw loaded data. */ setRawLastLoaded(data: unknown): void { this.state.lastLoadedRawData = data; } /** * Sets the flag indicating if it's the initial render cycle * @param value - the value of the flag. */ setIsInitialRender(value: boolean): void { this.state.isInitialRender = value; } /** * Sets the flag indicating that the process of inserting components into the DOM tree is currently in progress * @param value */ setIsDomInsertInProgress(value: boolean): void { this.privateState.isDomInsertInProgress = value; } /** * Sets the flag indicating if requests are stopped and the component won't make any more requests * until the lifecycle is refreshed. * * @param value - the value of the flag. */ setIsRequestsStopped(value: boolean): void { this.state.areRequestsStopped = value; } /** * Sets a flag indicating whether the tombstones slot is in the viewport. * @param value */ setIsTombstonesInView(value: boolean): void { this.state.isTombstonesInView = value; } /** * Sets the flag indicating if the component's lifecycle is done * @param value - the value of the flag. */ setIsLifecycleDone(value: boolean): void { this.state.isLifecycleDone = value; } /** * Sets the flag indicating if the component is currently loading data * @param value - the value of the flag. */ setIsLoadingInProgress(value: boolean): void { this.state.isLoadingInProgress = value; } /** * Sets a flag indicating whether the last load operation ended with an error * @param value - the value to set. */ setIsLastErrored(value: boolean): void { this.state.isLastErrored = value; } /** * Sets the maximum viewed index based on the passed component's index * @param component - the component to compare and update the maximum viewed index. */ setMaxViewedIndex(component: MountedChild): void { const {state} = this, {childIndex} = component; if (isItem(component) && (state.maxViewedItem == null || state.maxViewedItem < component.itemIndex)) { state.maxViewedItem = component.itemIndex; state.remainingItems = state.items.length - 1 - state.maxViewedItem; } if (state.maxViewedChild == null || state.maxViewedChild < childIndex) { state.maxViewedChild = component.childIndex; state.remainingChildren = state.childList.length - 1 - state.maxViewedChild; } this.updateRemainingChildren(); } /** * Returns the cursor indicating the last index of the last rendered data element */ getDataOffset(): number { return this.state.dataOffset; } /** * Returns the value of the flag indicating whether the process * of inserting components into the DOM tree is currently in progress */ getIsDomInsertInProgress(): boolean { return this.privateState.isDomInsertInProgress; } /** * Updates the cursor indicating the last index of the last rendered data element */ updateDataOffset(): void { const {ctx, state} = this, current = this.getDataOffset(), chunkSize = ctx.getChunkSize(state); this.state.dataOffset = current + chunkSize; } /** * Updates the state of the tillEnd-like fields. * Calculates the remaining number of child elements until the end and the remaining number of items until the end. */ updateRemainingChildren(): void { const {state} = this; if (state.maxViewedChild == null) { state.remainingChildren = state.childList.length - 1; } else { state.remainingChildren = state.childList.length - 1 - state.maxViewedChild; } if (state.maxViewedItem == null) { state.remainingItems = state.items.length - 1; } else { state.remainingItems = state.items.length - 1 - state.maxViewedItem; } } }