import type { Signal } from 'solid-js' import { comparer } from '@wovin/core/mobx' import { Logger } from 'besonders-logger' import { createSignal } from 'solid-js' const { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line unused-imports/no-unused-vars const appStartTimeStamp = Date.now() const p = performance.now() let precision = 0 // milliseconds since epoch (100nanosecond "precision") export function utcMsTs(): number { const now = new Date() const newPrecision = Math.round(performance.now() - p) precision = newPrecision === precision ? newPrecision + 1 : newPrecision // ensure 1ms difference - basically return appStartTimeStamp + precision + (now.getTimezoneOffset() * 60 * 1000) } // FROM: https://stackoverflow.com/a/73123810/1633985 export function useLocalStorage( key: string, defaultValue: T, storage = localStorage, ): Signal { const initialValue = storage.getItem(key) ? JSON.parse(storage.getItem(key)) as T : defaultValue const [value, setValue] = createSignal(initialValue) const setValueAndStore = ((arg) => { const v = setValue(arg) storage.setItem(key, JSON.stringify(v)) return v }) as typeof setValue return [value, setValueAndStore] } /** * returns `arrB` but re-uses entries from `arrA` if equal * For use in , as that checks by identity if re-render is needed */ export function arrayReUseItemsIfEqual(arrA: T[], arrB: T[], compareWith = comparer.structural): T[] { if (!arrA?.length || !arrB?.length) return arrB const newArrB = Array.from({ length: arrB.length }) for (let i = 0; i < arrB.length; i++) { const elemB = arrB[i] const matchingFromA = arrA.find(elemA => compareWith(elemA, elemB)) if (matchingFromA) { newArrB[i] = matchingFromA DEBUG(`[arrayReuseItems] re-using`, { elemB, matchingFromA, arrA, arrB }) } else { newArrB[i] = elemB } } DEBUG(`[arrayReuseItems]`, { arrA, arrB, newArrB }) return newArrB } export function findDeeplyNested(obj: Record, predicate: (val: any) => boolean) { if (Array.isArray(obj)) { for (const item of obj) { if (predicate(item)) return item const result = findDeeplyNested(item, predicate) if (result) { return result } } } else if (typeof obj === 'object' && obj !== null) { for (const key in obj) { if (predicate(obj[key])) return obj[key] const result = findDeeplyNested(obj[key], predicate) if (result) { return result } } } return null } export function findAllDeeplyNested(obj: Record, predicate: (val: any) => boolean) { const matches = new Set() if (Array.isArray(obj)) { for (const item of obj) { if (predicate(item)) matches.add(item) for (const match of findAllDeeplyNested(item, predicate)) { matches.add(match) } } } else if (typeof obj === 'object' && obj !== null) { for (const key in obj) { if (predicate(obj[key])) matches.add(obj[key]) for (const match of findAllDeeplyNested(obj[key], predicate)) { matches.add(match) } } } return matches }