UNPKG

react-native-wishlist

Version:
160 lines (157 loc) 5.36 kB
import { useMemo } from 'react'; import { useOnFlushCallback, useScheduleSyncUp } from './OrchestratorBinding'; import { useWishlistContext } from './WishlistContext'; export function useInternalWishlistData(wishlistId, initialData) { const scheduleSyncUp = useScheduleSyncUp(wishlistId); const data = useMemo(() => { return () => { 'worklet'; if (!global.dataCtx) { global.dataCtx = {}; } if (!global.dataCtx[wishlistId]) { function createItemsDataStructure(initialData) { // classes doesn't work :( // TODO it can be implmented so that all ops are O(log n) const thiz = { deque: initialData, getIndex: function getIndex(key) { // That's linear but can be log n (only for testing) for (let i = 0; i < this.deque.length; ++i) { if (this.deque[i].key === key) { return i; } } return undefined; }, at: function at(index) { if (index == undefined || index >= this.length() || index < 0) { return undefined; } return this.deque[index]; }, length: function length() { return this.deque.length; }, forKey: function forKey(key) { const index = this.getIndex(key); if (!index) { return undefined; } return this.at(index); }, get: function get(key) { return this.forKey(key); }, setItem: function setItem(key, value) { const index = this.getIndex(key); this.setAt(index, value); }, set: function set(key, value) { return this.setItem(key, value); }, setAt: function setAt(index, value) { this.deque[index] = value; if (this.isTrackingChanges) { this.dirtyKeys.add(value.key); } }, push: function push(value) { this.deque.push(value); }, unshift: function unshift(value) { this.deque.unshift(value); }, applyChanges: function applyChanges(pendingUpdates) { this.isTrackingChanges = true; for (let updateJob of pendingUpdates) { updateJob(this); } this.isTrackingChanges = false; const res = this.dirtyKeys; this.dirtyKeys = new Set(); return res; }, dirtyKeys: new Set(), isTrackingChanges: false }; return thiz; } function deepClone(x) { if (x.map != null) { return x.map(ele => deepClone(ele)); } if (typeof x === 'object') { const res = {}; for (let key of Object.keys(x)) { res[key] = deepClone(x[key]); } return res; } return x; } const initialDataCopy__next = deepClone(initialData); const initialDataCopy__cur = deepClone(initialData); const __nextCopy = createItemsDataStructure(initialDataCopy__next); const __currentlyRenderedCopy = createItemsDataStructure(initialDataCopy__cur); const pendingUpdates = []; function update(updateJob, callback) { updateJob(__nextCopy); pendingUpdates.push(dataCopy => { const result = updateJob(dataCopy); callback === null || callback === void 0 ? void 0 : callback(result); }); scheduleSyncUp(); } function at(index) { return __currentlyRenderedCopy.at(index); } function length() { return __currentlyRenderedCopy.length(); } function forKey(key) { return __currentlyRenderedCopy.forKey(key); } const internalData = { update, at, forKey, length, __currentlyRenderedCopy, __nextCopy, pendingUpdates }; global.dataCtx[wishlistId] = internalData; } return global.dataCtx[wishlistId]; }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useOnFlushCallback(viewportObserver => { 'worklet'; const pendingUpdates = data().pendingUpdates; const pendingUpdatesCopy = pendingUpdates.splice(0, pendingUpdates.length); const dirty = data().__currentlyRenderedCopy.applyChanges(pendingUpdatesCopy); const window = viewportObserver.getAllVisibleItems(); // Right now we only support adding items but it can be easily extended const newIndex = data().__currentlyRenderedCopy.getIndex(window[0].key); viewportObserver.updateIndices(newIndex); const dirtyItems = []; let i = 0; for (let item of window) { if (dirty.has(item.key)) { dirtyItems.push(i); } i++; } viewportObserver.markItemsDirty(dirtyItems); }, wishlistId); return data; } export function useData() { const { data } = useWishlistContext(); return data; } //# sourceMappingURL=WishlistData.js.map