UNPKG

@react-native-ohos/flash-list

Version:

FlashList is a more performant FlatList replacement

130 lines 7.3 kB
"use strict"; /** * MIT License * * Copyright (C) 2024 Huawei Device Co., Ltd. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var CustomError_1 = tslib_1.__importDefault(require("../errors/CustomError")); var ExceptionList_1 = tslib_1.__importDefault(require("../errors/ExceptionList")); /** * Helper class for computing viewable items based on the passed `viewabilityConfig`. * Note methods in this class will be invoked on every scroll and should be optimized for performance. */ var ViewabilityHelper = /** @class */ (function () { function ViewabilityHelper(viewabilityConfig, viewableIndicesChanged) { /** * Viewable indices regardless of the viewability config */ this.possiblyViewableIndices = []; this.hasInteracted = false; this.viewableIndices = []; this.lastReportedViewableIndices = []; this.timers = new Set(); this.viewabilityConfig = viewabilityConfig; this.viewableIndicesChanged = viewableIndicesChanged; } ViewabilityHelper.prototype.dispose = function () { // Clean up on dismount this.timers.forEach(clearTimeout); }; ViewabilityHelper.prototype.updateViewableItems = function (horizontal, scrollOffset, listSize, getLayout, viewableIndices) { var _this = this; var _a, _b, _c, _d, _e, _f, _g, _h; if (viewableIndices !== undefined) { this.possiblyViewableIndices = viewableIndices; } if (((_a = this.viewabilityConfig) === null || _a === void 0 ? void 0 : _a.itemVisiblePercentThreshold) !== null && ((_b = this.viewabilityConfig) === null || _b === void 0 ? void 0 : _b.itemVisiblePercentThreshold) !== undefined && ((_c = this.viewabilityConfig) === null || _c === void 0 ? void 0 : _c.viewAreaCoveragePercentThreshold) !== null && ((_d = this.viewabilityConfig) === null || _d === void 0 ? void 0 : _d.viewAreaCoveragePercentThreshold) !== undefined) { throw new CustomError_1.default(ExceptionList_1.default.multipleViewabilityThresholdTypesNotSupported); } if (((_f = (_e = this.viewabilityConfig) === null || _e === void 0 ? void 0 : _e.waitForInteraction) !== null && _f !== void 0 ? _f : false) && !this.hasInteracted) { return; } var newViewableIndices = this.possiblyViewableIndices.filter(function (index) { var _a, _b; return _this.isItemViewable(index, horizontal, scrollOffset, listSize, (_a = _this.viewabilityConfig) === null || _a === void 0 ? void 0 : _a.viewAreaCoveragePercentThreshold, (_b = _this.viewabilityConfig) === null || _b === void 0 ? void 0 : _b.itemVisiblePercentThreshold, getLayout); }); this.viewableIndices = newViewableIndices; var minimumViewTime = (_h = (_g = this.viewabilityConfig) === null || _g === void 0 ? void 0 : _g.minimumViewTime) !== null && _h !== void 0 ? _h : 250; // Setting default to 250. Default of 0 can impact performance when user scrolls fast. if (minimumViewTime > 0) { var timeoutId_1 = setTimeout(function () { _this.timers.delete(timeoutId_1); _this.checkViewableIndicesChanges(newViewableIndices); }, minimumViewTime); this.timers.add(timeoutId_1); } else { this.checkViewableIndicesChanges(newViewableIndices); } }; ViewabilityHelper.prototype.checkViewableIndicesChanges = function (newViewableIndices) { var _this = this; // Check if all viewable indices are still available (applicable if minimumViewTime > 0) var currentlyNewViewableIndices = newViewableIndices.filter(function (index) { return _this.viewableIndices.includes(index); }); var newlyVisibleItems = currentlyNewViewableIndices.filter(function (index) { return !_this.lastReportedViewableIndices.includes(index); }); var newlyNonvisibleItems = this.lastReportedViewableIndices.filter(function (index) { return !currentlyNewViewableIndices.includes(index); }); if (newlyVisibleItems.length > 0 || newlyNonvisibleItems.length > 0) { this.lastReportedViewableIndices = currentlyNewViewableIndices; this.viewableIndicesChanged(currentlyNewViewableIndices, newlyVisibleItems, newlyNonvisibleItems); } }; ViewabilityHelper.prototype.clearLastReportedViewableIndices = function () { this.lastReportedViewableIndices = []; }; ViewabilityHelper.prototype.isItemViewable = function (index, horizontal, scrollOffset, listSize, viewAreaCoveragePercentThreshold, itemVisiblePercentThreshold, getLayout) { var itemLayout = getLayout(index); if (itemLayout === undefined) { return false; } var itemTop = (horizontal ? itemLayout.x : itemLayout.y) - scrollOffset; var itemSize = horizontal ? itemLayout.width : itemLayout.height; var listMainSize = horizontal ? listSize.width : listSize.height; var pixelsVisible = Math.min(itemTop + itemSize, listMainSize) - Math.max(itemTop, 0); // Always consider item fully viewable if it is fully visible, regardless of the `viewAreaCoveragePercentThreshold` if (pixelsVisible === itemSize) { return true; } // Skip checking item if it's not visible at all if (pixelsVisible === 0) { return false; } var viewAreaMode = viewAreaCoveragePercentThreshold !== null && viewAreaCoveragePercentThreshold !== undefined; var percent = viewAreaMode ? pixelsVisible / listMainSize : pixelsVisible / itemSize; var viewableAreaPercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold * 0.01 : (itemVisiblePercentThreshold !== null && itemVisiblePercentThreshold !== void 0 ? itemVisiblePercentThreshold : 0) * 0.01; return percent >= viewableAreaPercentThreshold; }; return ViewabilityHelper; }()); exports.default = ViewabilityHelper; //# sourceMappingURL=ViewabilityHelper.js.map