react-native-wishlist
Version:
The fastest List component for React Native.
160 lines (157 loc) • 5.36 kB
JavaScript
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