Skip to content

Commit 0bc1d22

Browse files
committed
ENG-1479: Port suggestive mode settings to dual-read (#845)
* ENG-1479: Port suggestive mode settings to dual-read Add dual-read routing to getFeatureFlag for flags with legacy counterparts. FEATURE_FLAG_LEGACY_MAP maps "Suggestive mode enabled" and "Enable left sidebar" to their config tree reads, gated by isNewSettingsStoreEnabled(). Flags without legacy entries go straight to block props (no behavior change). Migrate value reads from getFormattedConfigTree() / extensionAPI.settings to accessors: - index.ts: getUidAndBooleanSetting → getFeatureFlag (accessor handles legacy fallback now) - AdminPanel: suggestiveModeEnabled.value → getFeatureFlag in both FeatureFlagsTab and main component. Removed unused useMemo. - SuggestiveModeSettings: includePageRelations state init → getGlobalSetting. Dropped initialValue from both GlobalFlagPanels. - hyde.ts: orphan extensionAPI.settings.get() reads → getGlobalSetting. Fixes bug where sync config toggles had no runtime effect (keys were never written by any code). Structural UIDs remain with getFormattedConfigTree(). pageGroups.groups NOT migrated — type mismatch (legacy PageGroup has UIDs, Zod PageGroup does not). Deferred to ENG-1470. * Align hyde.ts fallback defaults with Zod schema * Fix eslint naming-convention warnings in FEATURE_FLAG_LEGACY_MAP * Add TODO(ENG-1484) for suggestive mode reactivity
1 parent 47411c2 commit 0bc1d22

5 files changed

Lines changed: 58 additions & 35 deletions

File tree

apps/roam/src/components/settings/AdminPanel.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ const FeatureFlagsTab = (): React.ReactElement => {
360360
}, []);
361361

362362
const [suggestiveModeEnabled, setSuggestiveModeEnabled] = useState(
363-
settings.suggestiveModeEnabled.value || false,
363+
getFeatureFlag("Suggestive mode enabled"),
364364
);
365365
const [suggestiveModeUid, setSuggestiveModeUid] = useState(
366366
settings.suggestiveModeEnabled.uid,
@@ -424,6 +424,8 @@ const FeatureFlagsTab = (): React.ReactElement => {
424424
<p>Are you sure you want to proceed?</p>
425425
</Alert>
426426

427+
{/* TODO(ENG-1484): Add pull watcher reactivity so toggling suggestive mode
428+
starts/stops sync and shows the tab without requiring a reload. */}
427429
<Alert
428430
isOpen={isInstructionOpen}
429431
onConfirm={() => window.location.reload()}
@@ -498,10 +500,6 @@ const FeatureFlagsTab = (): React.ReactElement => {
498500

499501
const AdminPanel = (): React.ReactElement => {
500502
const [selectedTabId, setSelectedTabId] = useState<TabId>("admin");
501-
const settings = useMemo(() => {
502-
refreshConfigTree();
503-
return getFormattedConfigTree();
504-
}, []);
505503

506504
return (
507505
<Tabs
@@ -536,7 +534,7 @@ const AdminPanel = (): React.ReactElement => {
536534
</div>
537535
}
538536
/>
539-
{settings.suggestiveModeEnabled.value && (
537+
{getFeatureFlag("Suggestive mode enabled") && (
540538
<Tab
541539
id="suggestive-mode-settings"
542540
title="Suggestive mode"

apps/roam/src/components/settings/SuggestiveModeSettings.tsx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { DISCOURSE_CONFIG_PAGE_TITLE } from "~/utils/renderNodeConfigPage";
99
import { createOrUpdateDiscourseEmbedding } from "~/utils/syncDgNodesToSupabase";
1010
import { render as renderToast } from "roamjs-components/components/Toast";
1111
import { GlobalFlagPanel } from "./components/BlockPropSettingPanels";
12+
import { getGlobalSetting } from "~/components/settings/utils/accessors";
1213
import posthog from "posthog-js";
1314

1415
const SuggestiveModeSettings = () => {
@@ -20,7 +21,10 @@ const SuggestiveModeSettings = () => {
2021
const pageGroupsUid = settings.suggestiveMode.pageGroups.uid;
2122

2223
const [includePageRelations, setIncludePageRelations] = useState(
23-
settings.suggestiveMode.includePageRelations.value,
24+
getGlobalSetting<boolean>([
25+
"Suggestive mode",
26+
"Include current page relations",
27+
]) ?? false,
2428
);
2529

2630
useEffect(() => {
@@ -69,8 +73,9 @@ const SuggestiveModeSettings = () => {
6973
title="Sync config"
7074
panel={
7175
<div className="flex flex-col gap-4 p-1">
72-
{/* TODO: Titles kept as Title Case to match legacy readers in getSuggestiveModeConfigSettings.ts.
73-
Update titles to Sentence case once read side is migrated to block props. */}
76+
{/* TODO(ENG-1469): Titles kept as Title Case because getSuggestiveModeConfigSettings.ts
77+
still reads from the block tree expecting these strings. Update to Sentence case
78+
once the aggregator is refactored to read from block props. */}
7479
<div className="sync-config-settings">
7580
<GlobalFlagPanel
7681
title="Include Current Page Relations"
@@ -79,9 +84,6 @@ const SuggestiveModeSettings = () => {
7984
"Suggestive mode",
8085
"Include current page relations",
8186
]}
82-
initialValue={
83-
settings.suggestiveMode.includePageRelations.value
84-
}
8587
order={0}
8688
uid={settings.suggestiveMode.includePageRelations.uid}
8789
parentUid={effectiveSuggestiveModeUid}
@@ -99,9 +101,6 @@ const SuggestiveModeSettings = () => {
99101
"Suggestive mode",
100102
"Include parent and child blocks",
101103
]}
102-
initialValue={
103-
settings.suggestiveMode.includeParentAndChildren.value
104-
}
105104
value={includePageRelations ? true : undefined}
106105
order={1}
107106
uid={settings.suggestiveMode.includeParentAndChildren.uid}

apps/roam/src/components/settings/utils/accessors.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -661,9 +661,40 @@ export const getFeatureFlags = (): FeatureFlags => {
661661
return FeatureFlagsSchema.parse(blockProps || {});
662662
};
663663

664+
/* eslint-disable @typescript-eslint/naming-convention */
665+
const FEATURE_FLAG_LEGACY_MAP: Partial<
666+
Record<keyof FeatureFlags, () => boolean>
667+
> = {
668+
"Suggestive mode enabled": () =>
669+
getFormattedConfigTree().suggestiveModeEnabled.value,
670+
"Enable left sidebar": () =>
671+
getFormattedConfigTree().leftSidebarEnabled.value,
672+
};
673+
/* eslint-enable @typescript-eslint/naming-convention */
674+
664675
export const getFeatureFlag = (key: keyof FeatureFlags): boolean => {
676+
const legacyReader = FEATURE_FLAG_LEGACY_MAP[key];
677+
678+
if (!legacyReader) {
679+
// Block-props-only flag (no legacy equivalent)
680+
const flags = getFeatureFlags();
681+
return flags[key];
682+
}
683+
684+
if (!isNewSettingsStoreEnabled()) {
685+
return legacyReader();
686+
}
687+
665688
const flags = getFeatureFlags();
666-
return flags[key];
689+
const blockPropsValue = flags[key];
690+
const legacyValue = legacyReader();
691+
if (blockPropsValue !== legacyValue) {
692+
console.warn(`[DG Dual-Read] Mismatch at Feature Flag > ${key}`, {
693+
blockProps: blockPropsValue,
694+
legacy: legacyValue,
695+
});
696+
}
697+
return blockPropsValue;
667698
};
668699

669700
export const isNewSettingsStoreEnabled = (): boolean => {

apps/roam/src/index.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,12 @@ import {
3131
setSyncActivity,
3232
} from "./utils/syncDgNodesToSupabase";
3333
import { initPluginTimer } from "./utils/pluginTimer";
34-
import { getUidAndBooleanSetting } from "./utils/getExportSettings";
35-
import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByParentUid";
36-
import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTitle";
37-
import { DISCOURSE_CONFIG_PAGE_TITLE } from "./utils/renderNodeConfigPage";
3834
import { initPostHog } from "./utils/posthog";
3935
import { initSchema } from "./components/settings/utils/init";
40-
import { getPersonalSetting } from "./components/settings/utils/accessors";
36+
import {
37+
getFeatureFlag,
38+
getPersonalSetting,
39+
} from "./components/settings/utils/accessors";
4140

4241
export const DEFAULT_CANVAS_PAGE_FORMAT = "Canvas/*";
4342

@@ -112,12 +111,7 @@ export default runExtension(async (onloadArgs) => {
112111
document.addEventListener("input", discourseNodeSearchTriggerListener);
113112
document.addEventListener("selectionchange", nodeCreationPopoverListener);
114113

115-
const isSuggestiveModeEnabled = getUidAndBooleanSetting({
116-
tree: getBasicTreeByParentUid(
117-
getPageUidByPageTitle(DISCOURSE_CONFIG_PAGE_TITLE),
118-
),
119-
text: "(BETA) Suggestive Mode Enabled",
120-
}).value;
114+
const isSuggestiveModeEnabled = getFeatureFlag("Suggestive mode enabled");
121115

122116
if (isSuggestiveModeEnabled) {
123117
initializeSupabaseSync();

apps/roam/src/utils/hyde.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import { render as renderToast } from "roamjs-components/components/Toast";
55
import findDiscourseNode from "./findDiscourseNode";
66
import { nextApiRoot } from "@repo/utils/execContext";
77
import { DiscourseNode } from "./getDiscourseNodes";
8-
import getExtensionAPI from "roamjs-components/util/extensionApiContext";
98
import { getNodesByType } from "@repo/database/lib/queries";
109
import getAllReferencesOnPage from "./getAllReferencesOnPage";
10+
import { getGlobalSetting } from "~/components/settings/utils/accessors";
1111

1212
type ApiEmbeddingResponse = {
1313
data: Array<{
@@ -415,15 +415,16 @@ export const performHydeSearch = async ({
415415
return [];
416416
}
417417

418-
const extensionAPI = getExtensionAPI();
419418
const shouldGrabFromReferencedPages =
420-
(extensionAPI.settings.get(
421-
"context-grab-from-referenced-pages",
422-
) as boolean) ?? true;
419+
getGlobalSetting<boolean>([
420+
"Suggestive mode",
421+
"Include current page relations",
422+
]) ?? false;
423423
const shouldGrabParentChildContext =
424-
(extensionAPI.settings.get(
425-
"context-grab-parent-child-context",
426-
) as boolean) ?? true;
424+
getGlobalSetting<boolean>([
425+
"Suggestive mode",
426+
"Include parent and child blocks",
427+
]) ?? false;
427428

428429
let candidateNodesForHyde: SuggestedNode[] = [];
429430

0 commit comments

Comments
 (0)