Skip to content

Commit 73561dc

Browse files
authored
new utility fn, deepCompareReturnPrev. use for settings prefix atom to do a deep equal (#1630)
1 parent 904d942 commit 73561dc

File tree

4 files changed

+28
-13
lines changed

4 files changed

+28
-13
lines changed

frontend/app/app.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import { ContextMenuModel } from "@/store/contextmenu";
66
import {
77
atoms,
88
createBlock,
9+
getSettingsPrefixAtom,
910
globalStore,
1011
isDev,
1112
PLATFORM,
1213
removeFlashError,
13-
useSettingsPrefixAtom,
1414
} from "@/store/global";
1515
import { appHandleKeyDown } from "@/store/keymodel";
1616
import { getElemAsStr } from "@/util/focusutil";
@@ -123,7 +123,7 @@ async function handleContextMenu(e: React.MouseEvent<HTMLDivElement>) {
123123
}
124124

125125
function AppSettingsUpdater() {
126-
const windowSettingsAtom = useSettingsPrefixAtom("window");
126+
const windowSettingsAtom = getSettingsPrefixAtom("window");
127127
const windowSettings = useAtomValue(windowSettingsAtom);
128128
useEffect(() => {
129129
const isTransparentOrBlur =

frontend/app/store/global.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
import { getLayoutModelForStaticTab } from "@/layout/lib/layoutModelHooks";
1111
import { getWebServerEndpoint } from "@/util/endpoints";
1212
import { fetch } from "@/util/fetchutil";
13-
import { getPrefixedSettings, isBlank } from "@/util/util";
13+
import { deepCompareReturnPrev, getPrefixedSettings, isBlank } from "@/util/util";
1414
import { atom, Atom, PrimitiveAtom, useAtomValue } from "jotai";
1515
import { globalStore } from "./jotaiStore";
1616
import { modalsModel } from "./modalmodel";
@@ -314,16 +314,15 @@ function useSettingsKeyAtom<T extends keyof SettingsType>(key: T): SettingsType[
314314
return useAtomValue(getSettingsKeyAtom(key));
315315
}
316316

317-
function useSettingsPrefixAtom(prefix: string): Atom<SettingsType> {
318-
// TODO: use a shallow equal here to make this more efficient
319-
let settingsPrefixAtom = settingsAtomCache.get(prefix + ":") as Atom<SettingsType>;
317+
function getSettingsPrefixAtom(prefix: string): Atom<SettingsType> {
318+
let settingsPrefixAtom = settingsAtomCache.get(prefix + ":");
320319
if (settingsPrefixAtom == null) {
320+
// create a stable, closured reference to use as the deepCompareReturnPrev key
321+
const cacheKey = {};
321322
settingsPrefixAtom = atom((get) => {
322323
const settings = get(atoms.settingsAtom);
323-
if (settings == null) {
324-
return {};
325-
}
326-
return getPrefixedSettings(settings, prefix);
324+
const newValue = getPrefixedSettings(settings, prefix);
325+
return deepCompareReturnPrev(cacheKey, newValue);
327326
});
328327
settingsAtomCache.set(prefix + ":", settingsPrefixAtom);
329328
}
@@ -674,6 +673,7 @@ export {
674673
getObjectId,
675674
getOverrideConfigAtom,
676675
getSettingsKeyAtom,
676+
getSettingsPrefixAtom,
677677
getUserName,
678678
globalStore,
679679
initGlobal,
@@ -700,6 +700,5 @@ export {
700700
useBlockMetaKeyAtom,
701701
useOverrideConfigAtom,
702702
useSettingsKeyAtom,
703-
useSettingsPrefixAtom,
704703
WOS,
705704
};

frontend/app/view/term/term.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ import {
1717
getConnStatusAtom,
1818
getOverrideConfigAtom,
1919
getSettingsKeyAtom,
20+
getSettingsPrefixAtom,
2021
globalStore,
2122
useBlockAtom,
22-
useSettingsPrefixAtom,
2323
WOS,
2424
} from "@/store/global";
2525
import * as services from "@/store/services";
@@ -773,7 +773,7 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
773773
const viewRef = React.useRef<HTMLDivElement>(null);
774774
const connectElemRef = React.useRef<HTMLDivElement>(null);
775775
const [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", blockId));
776-
const termSettingsAtom = useSettingsPrefixAtom("term");
776+
const termSettingsAtom = getSettingsPrefixAtom("term");
777777
const termSettings = jotai.useAtomValue(termSettingsAtom);
778778
let termMode = blockData?.meta?.["term:mode"] ?? "term";
779779
if (termMode != "term" && termMode != "vdom") {

frontend/util/util.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import base64 from "base64-js";
55
import clsx from "clsx";
66
import { Atom, atom, Getter, SetStateAction, Setter, useAtomValue } from "jotai";
77
import { debounce, throttle } from "throttle-debounce";
8+
const prevValueCache = new WeakMap<any, any>(); // stores a previous value for a deep equal comparison (used with the deepCompareReturnPrev function)
89

910
function isBlank(str: string): boolean {
1011
return str == null || str == "";
@@ -42,6 +43,20 @@ function boundNumber(num: number, min: number, max: number): number {
4243
return Math.min(Math.max(num, min), max);
4344
}
4445

46+
// key must be a suitable weakmap key. pass the new value
47+
// it will return the prevValue (for object equality) if the new value is deep equal to the prev value
48+
function deepCompareReturnPrev(key: any, newValue: any): any {
49+
if (key == null) {
50+
return newValue;
51+
}
52+
const previousValue = prevValueCache.get(key);
53+
if (previousValue !== undefined && JSON.stringify(newValue) === JSON.stringify(previousValue)) {
54+
return previousValue;
55+
}
56+
prevValueCache.set(key, newValue);
57+
return newValue;
58+
}
59+
4560
// works for json-like objects (arrays, objects, strings, numbers, booleans)
4661
function jsonDeepEqual(v1: any, v2: any): boolean {
4762
if (v1 === v2) {
@@ -294,6 +309,7 @@ export {
294309
base64ToString,
295310
boundNumber,
296311
countGraphemes,
312+
deepCompareReturnPrev,
297313
fireAndForget,
298314
getPrefixedSettings,
299315
getPromiseState,

0 commit comments

Comments
 (0)