diff options
author | Paul Frazee <pfrazee@gmail.com> | 2024-04-30 21:06:51 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-30 21:06:51 -0700 |
commit | 31cb3e54222afc0b56e9d3e7997e2229797ff11e (patch) | |
tree | d837a8d0f7e08b1d97e22b77c69bdc93bad2554c /src/lib | |
parent | 39807a86309ccfeeffbd054808c0e78e42ff940e (diff) | |
download | voidsky-31cb3e54222afc0b56e9d3e7997e2229797ff11e.tar.zst |
Performance improvements: structural sharing & moderation opts context (#3785)
* Fix: correctly apply structural sharing to preferences object * Move moderation opts into a context * Fix import * Remove log * Pass userdid directly * Pass moderationPrefs directly
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/functions.ts | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/lib/functions.ts b/src/lib/functions.ts index b45c7fa6d..e0d44ce2d 100644 --- a/src/lib/functions.ts +++ b/src/lib/functions.ts @@ -9,3 +9,90 @@ export function dedupArray<T>(arr: T[]): T[] { const s = new Set(arr) return [...s] } + +/** + * Taken from @tanstack/query-core utils.ts + * Modified to support Date object comparisons + * + * This function returns `a` if `b` is deeply equal. + * If not, it will replace any deeply equal children of `b` with those of `a`. + * This can be used for structural sharing between JSON values for example. + */ +export function replaceEqualDeep(a: any, b: any): any { + if (a === b) { + return a + } + + if (a instanceof Date && b instanceof Date) { + return a.getTime() === b.getTime() ? a : b + } + + const array = isPlainArray(a) && isPlainArray(b) + + if (array || (isPlainObject(a) && isPlainObject(b))) { + const aItems = array ? a : Object.keys(a) + const aSize = aItems.length + const bItems = array ? b : Object.keys(b) + const bSize = bItems.length + const copy: any = array ? [] : {} + + let equalItems = 0 + + for (let i = 0; i < bSize; i++) { + const key = array ? i : bItems[i] + if ( + !array && + a[key] === undefined && + b[key] === undefined && + aItems.includes(key) + ) { + copy[key] = undefined + equalItems++ + } else { + copy[key] = replaceEqualDeep(a[key], b[key]) + if (copy[key] === a[key] && a[key] !== undefined) { + equalItems++ + } + } + } + + return aSize === bSize && equalItems === aSize ? a : copy + } + + return b +} + +export function isPlainArray(value: unknown) { + return Array.isArray(value) && value.length === Object.keys(value).length +} + +// Copied from: https://github.com/jonschlinkert/is-plain-object +export function isPlainObject(o: any): o is Object { + if (!hasObjectPrototype(o)) { + return false + } + + // If has no constructor + const ctor = o.constructor + if (ctor === undefined) { + return true + } + + // If has modified prototype + const prot = ctor.prototype + if (!hasObjectPrototype(prot)) { + return false + } + + // If constructor does not have an Object-specific method + if (!prot.hasOwnProperty('isPrototypeOf')) { + return false + } + + // Most likely a plain Object + return true +} + +function hasObjectPrototype(o: any): boolean { + return Object.prototype.toString.call(o) === '[object Object]' +} |