new utility fn, deepCompareReturnPrev. use for settings prefix atom to do a deep equal (#1630)

This commit is contained in:
Mike Sawka 2024-12-26 11:09:48 -08:00 committed by GitHub
parent 904d942c4c
commit 73561dc12d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 28 additions and 13 deletions

View File

@ -6,11 +6,11 @@ import { ContextMenuModel } from "@/store/contextmenu";
import {
atoms,
createBlock,
getSettingsPrefixAtom,
globalStore,
isDev,
PLATFORM,
removeFlashError,
useSettingsPrefixAtom,
} from "@/store/global";
import { appHandleKeyDown } from "@/store/keymodel";
import { getElemAsStr } from "@/util/focusutil";
@ -123,7 +123,7 @@ async function handleContextMenu(e: React.MouseEvent<HTMLDivElement>) {
}
function AppSettingsUpdater() {
const windowSettingsAtom = useSettingsPrefixAtom("window");
const windowSettingsAtom = getSettingsPrefixAtom("window");
const windowSettings = useAtomValue(windowSettingsAtom);
useEffect(() => {
const isTransparentOrBlur =

View File

@ -10,7 +10,7 @@ import {
import { getLayoutModelForStaticTab } from "@/layout/lib/layoutModelHooks";
import { getWebServerEndpoint } from "@/util/endpoints";
import { fetch } from "@/util/fetchutil";
import { getPrefixedSettings, isBlank } from "@/util/util";
import { deepCompareReturnPrev, getPrefixedSettings, isBlank } from "@/util/util";
import { atom, Atom, PrimitiveAtom, useAtomValue } from "jotai";
import { globalStore } from "./jotaiStore";
import { modalsModel } from "./modalmodel";
@ -314,16 +314,15 @@ function useSettingsKeyAtom<T extends keyof SettingsType>(key: T): SettingsType[
return useAtomValue(getSettingsKeyAtom(key));
}
function useSettingsPrefixAtom(prefix: string): Atom<SettingsType> {
// TODO: use a shallow equal here to make this more efficient
let settingsPrefixAtom = settingsAtomCache.get(prefix + ":") as Atom<SettingsType>;
function getSettingsPrefixAtom(prefix: string): Atom<SettingsType> {
let settingsPrefixAtom = settingsAtomCache.get(prefix + ":");
if (settingsPrefixAtom == null) {
// create a stable, closured reference to use as the deepCompareReturnPrev key
const cacheKey = {};
settingsPrefixAtom = atom((get) => {
const settings = get(atoms.settingsAtom);
if (settings == null) {
return {};
}
return getPrefixedSettings(settings, prefix);
const newValue = getPrefixedSettings(settings, prefix);
return deepCompareReturnPrev(cacheKey, newValue);
});
settingsAtomCache.set(prefix + ":", settingsPrefixAtom);
}
@ -674,6 +673,7 @@ export {
getObjectId,
getOverrideConfigAtom,
getSettingsKeyAtom,
getSettingsPrefixAtom,
getUserName,
globalStore,
initGlobal,
@ -700,6 +700,5 @@ export {
useBlockMetaKeyAtom,
useOverrideConfigAtom,
useSettingsKeyAtom,
useSettingsPrefixAtom,
WOS,
};

View File

@ -17,9 +17,9 @@ import {
getConnStatusAtom,
getOverrideConfigAtom,
getSettingsKeyAtom,
getSettingsPrefixAtom,
globalStore,
useBlockAtom,
useSettingsPrefixAtom,
WOS,
} from "@/store/global";
import * as services from "@/store/services";
@ -773,7 +773,7 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
const viewRef = React.useRef<HTMLDivElement>(null);
const connectElemRef = React.useRef<HTMLDivElement>(null);
const [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", blockId));
const termSettingsAtom = useSettingsPrefixAtom("term");
const termSettingsAtom = getSettingsPrefixAtom("term");
const termSettings = jotai.useAtomValue(termSettingsAtom);
let termMode = blockData?.meta?.["term:mode"] ?? "term";
if (termMode != "term" && termMode != "vdom") {

View File

@ -5,6 +5,7 @@ import base64 from "base64-js";
import clsx from "clsx";
import { Atom, atom, Getter, SetStateAction, Setter, useAtomValue } from "jotai";
import { debounce, throttle } from "throttle-debounce";
const prevValueCache = new WeakMap<any, any>(); // stores a previous value for a deep equal comparison (used with the deepCompareReturnPrev function)
function isBlank(str: string): boolean {
return str == null || str == "";
@ -42,6 +43,20 @@ function boundNumber(num: number, min: number, max: number): number {
return Math.min(Math.max(num, min), max);
}
// key must be a suitable weakmap key. pass the new value
// it will return the prevValue (for object equality) if the new value is deep equal to the prev value
function deepCompareReturnPrev(key: any, newValue: any): any {
if (key == null) {
return newValue;
}
const previousValue = prevValueCache.get(key);
if (previousValue !== undefined && JSON.stringify(newValue) === JSON.stringify(previousValue)) {
return previousValue;
}
prevValueCache.set(key, newValue);
return newValue;
}
// works for json-like objects (arrays, objects, strings, numbers, booleans)
function jsonDeepEqual(v1: any, v2: any): boolean {
if (v1 === v2) {
@ -294,6 +309,7 @@ export {
base64ToString,
boundNumber,
countGraphemes,
deepCompareReturnPrev,
fireAndForget,
getPrefixedSettings,
getPromiseState,