diff --git a/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx b/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx index f2bda0b83..01a2c289d 100644 --- a/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx @@ -22,6 +22,7 @@ import setBlockProps from "~/utils/setBlockProps"; import { DiscourseNodeSchema } from "./utils/zodSchema"; import { getGlobalSettings, setGlobalSetting } from "./utils/accessors"; import { GLOBAL_KEYS } from "./utils/settingKeys"; +import { invalidateDiscourseNodeTypeCaches } from "~/utils/discourseNodeTypeCache"; type DiscourseNodeConfigPanelProps = React.ComponentProps< CustomField["options"]["component"] @@ -60,6 +61,7 @@ const DiscourseNodeConfigPanel: React.FC = ({ await window.roamAlphaAPI.deletePage({ page: { uid }, }); + invalidateDiscourseNodeTypeCaches(); setNodes((prevNodes) => prevNodes.filter((nn) => nn.type !== uid)); refreshConfigTree(); setDeleteConfirmation(null); @@ -117,6 +119,7 @@ const DiscourseNodeConfigPanel: React.FC = ({ format, }), ); + invalidateDiscourseNodeTypeCaches(); setNodes([ ...nodes, { diff --git a/apps/roam/src/components/settings/utils/accessors.ts b/apps/roam/src/components/settings/utils/accessors.ts index 46fd70342..9ddcadd10 100644 --- a/apps/roam/src/components/settings/utils/accessors.ts +++ b/apps/roam/src/components/settings/utils/accessors.ts @@ -24,6 +24,10 @@ import { } from "~/utils/getExportSettings"; import { getSuggestiveModeConfigAndUids } from "~/utils/getSuggestiveModeConfigSettings"; import { getLeftSidebarSettings } from "~/utils/getLeftSidebarSettings"; +import { + getDiscourseNodeTypeCacheVersion, + invalidateDiscourseNodeTypeCaches, +} from "~/utils/discourseNodeTypeCache"; import { DG_BLOCK_PROP_SETTINGS_PAGE_TITLE, @@ -40,7 +44,12 @@ import { type DiscourseNodeSettings, type Condition as SchemaCondition, } from "./zodSchema"; -import { PERSONAL_KEYS, QUERY_KEYS, GLOBAL_KEYS } from "./settingKeys"; +import { + FEATURE_FLAG_KEYS, + PERSONAL_KEYS, + QUERY_KEYS, + GLOBAL_KEYS, +} from "./settingKeys"; const isRecord = (value: unknown): value is Record => typeof value === "object" && value !== null && !Array.isArray(value); @@ -716,7 +725,7 @@ export const getFeatureFlag = (key: keyof FeatureFlags): boolean => { }; export const isNewSettingsStoreEnabled = (): boolean => { - return getFeatureFlag("Use new settings store"); + return getFeatureFlag(FEATURE_FLAG_KEYS.useNewSettingsStore); }; export const readAllLegacyFeatureFlags = (): Partial => { @@ -724,7 +733,7 @@ export const readAllLegacyFeatureFlags = (): Partial => { for (const [key, reader] of Object.entries(FEATURE_FLAG_LEGACY_MAP)) { flags[key as keyof FeatureFlags] = reader(); } - flags["Use new settings store"] = false; + flags[FEATURE_FLAG_KEYS.useNewSettingsStore] = false; return flags; }; @@ -767,6 +776,10 @@ export const setFeatureFlag = ( keys: [STATIC_TOP_LEVEL_ENTRIES.featureFlags.key, key], value: validatedValue, }); + + if (key === FEATURE_FLAG_KEYS.useNewSettingsStore) { + invalidateDiscourseNodeTypeCaches(); + } }; export const getGlobalSettings = (): GlobalSettings => { @@ -880,7 +893,7 @@ export const bulkReadSettings = (): SettingsSnapshot => { const featureFlags = FeatureFlagsSchema.parse(featureFlagsProps || {}); - if (!featureFlags["Use new settings store"]) { + if (!featureFlags[FEATURE_FLAG_KEYS.useNewSettingsStore]) { return { featureFlags, globalSettings: readAllLegacyGlobalSettings() as GlobalSettings, @@ -967,7 +980,7 @@ export const getDiscourseNodeSetting = ( nodeType: string, keys: string[], ): T | undefined => { - if (!bulkReadSettings().featureFlags["Use new settings store"]) { + if (!bulkReadSettings().featureFlags[FEATURE_FLAG_KEYS.useNewSettingsStore]) { return getLegacyDiscourseNodeSetting(nodeType, keys) as T | undefined; } @@ -1023,6 +1036,7 @@ export const setDiscourseNodeSetting = ( } setBlockPropAtPath(pageUid, keys, value); + invalidateDiscourseNodeTypeCaches(); }; const addConditionUids = (conditions: SchemaCondition[]): Condition[] => @@ -1131,7 +1145,17 @@ const migrateNodeBlockProps = ( return migrated; }; +let allDiscourseNodesCache: { + version: number; + nodes: DiscourseNode[]; +} | null = null; + export const getAllDiscourseNodes = (): DiscourseNode[] => { + const cacheVersion = getDiscourseNodeTypeCacheVersion(); + if (allDiscourseNodesCache?.version === cacheVersion) { + return allDiscourseNodesCache.nodes; + } + const results = window.roamAlphaAPI.data.fast.q(` [:find ?uid ?title (pull ?page [:block/props]) :where @@ -1191,5 +1215,6 @@ export const getAllDiscourseNodes = (): DiscourseNode[] => { } } + allDiscourseNodesCache = { version: cacheVersion, nodes }; return nodes; }; diff --git a/apps/roam/src/components/settings/utils/migrateLegacyToBlockProps.ts b/apps/roam/src/components/settings/utils/migrateLegacyToBlockProps.ts index e026982a0..da29fa11b 100644 --- a/apps/roam/src/components/settings/utils/migrateLegacyToBlockProps.ts +++ b/apps/roam/src/components/settings/utils/migrateLegacyToBlockProps.ts @@ -23,6 +23,7 @@ import { getPersonalSettingsKey, } from "./zodSchema"; import type { z } from "zod"; +import { invalidateDiscourseNodeTypeCaches } from "~/utils/discourseNodeTypeCache"; const LOG_PREFIX = "[DG BlockProps Migration]"; const GRAPH_MIGRATION_MARKER = "Block props migrated"; @@ -63,11 +64,13 @@ const migrateSection = ({ blockUid, schema, legacyData, + onWrite, }: { label: string; blockUid: string; schema: z.ZodTypeAny; legacyData: Record; + onWrite?: () => void; }): boolean => { const currentProps = getBlockProps(blockUid); @@ -103,6 +106,7 @@ const migrateSection = ({ } setBlockProps(blockUid, parsedLegacy, false); + onWrite?.(); console.log(`${LOG_PREFIX} ${label}: migrated`); return true; }; @@ -156,6 +160,7 @@ const migrateDiscourseNodes = async (): Promise => { blockUid: nodePageUid, schema: DiscourseNodeSchema, legacyData, + onWrite: invalidateDiscourseNodeTypeCaches, }) ) { allOk = false; diff --git a/apps/roam/src/components/settings/utils/settingKeys.ts b/apps/roam/src/components/settings/utils/settingKeys.ts index be61da1a4..827f26100 100644 --- a/apps/roam/src/components/settings/utils/settingKeys.ts +++ b/apps/roam/src/components/settings/utils/settingKeys.ts @@ -1,4 +1,5 @@ import type { + FeatureFlags, PersonalSettings, QuerySettings, GlobalSettings, @@ -10,6 +11,13 @@ import type { SuggestiveRules, } from "./zodSchema"; +export const FEATURE_FLAG_KEYS = { + enableLeftSidebar: "Enable left sidebar", + duplicateNodeAlertEnabled: "Duplicate node alert enabled", + suggestiveModeOverlayEnabled: "Suggestive mode overlay enabled", + useNewSettingsStore: "Use new settings store", +} as const satisfies Record; + export const PERSONAL_KEYS = { discourseContextOverlay: "Discourse context overlay", textSelectionPopup: "Text selection popup", diff --git a/apps/roam/src/utils/discourseNodeTypeCache.ts b/apps/roam/src/utils/discourseNodeTypeCache.ts new file mode 100644 index 000000000..f5dc59a00 --- /dev/null +++ b/apps/roam/src/utils/discourseNodeTypeCache.ts @@ -0,0 +1,8 @@ +let discourseNodeTypeCacheVersion = 0; + +export const invalidateDiscourseNodeTypeCaches = (): void => { + discourseNodeTypeCacheVersion += 1; +}; + +export const getDiscourseNodeTypeCacheVersion = (): number => + discourseNodeTypeCacheVersion; diff --git a/apps/roam/src/utils/findDiscourseNode.ts b/apps/roam/src/utils/findDiscourseNode.ts index e0af95981..0c3e5ced3 100644 --- a/apps/roam/src/utils/findDiscourseNode.ts +++ b/apps/roam/src/utils/findDiscourseNode.ts @@ -1,8 +1,10 @@ import getDiscourseNodes, { type DiscourseNode } from "./getDiscourseNodes"; import matchDiscourseNode from "./matchDiscourseNode"; import type { SettingsSnapshot } from "~/components/settings/utils/accessors"; +import { getDiscourseNodeTypeCacheVersion } from "./discourseNodeTypeCache"; -const discourseNodeTypeCache: Record = {}; +let discourseNodeTypeCache: Record = {}; +let discourseNodeTypeCacheVersion = -1; const findDiscourseNode = ({ uid, @@ -15,6 +17,12 @@ const findDiscourseNode = ({ nodes?: DiscourseNode[]; snapshot?: SettingsSnapshot; }): DiscourseNode | false => { + const currentCacheVersion = getDiscourseNodeTypeCacheVersion(); + if (discourseNodeTypeCacheVersion !== currentCacheVersion) { + discourseNodeTypeCache = {}; + discourseNodeTypeCacheVersion = currentCacheVersion; + } + if (typeof discourseNodeTypeCache[uid] !== "undefined") { return discourseNodeTypeCache[uid]; }