Skip to content

Commit 29817b9

Browse files
committed
make feature flags fully reactive
1 parent d8b5b37 commit 29817b9

File tree

10 files changed

+80
-85
lines changed

10 files changed

+80
-85
lines changed

apps/roam/src/components/CreateRelationDialog.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import type { DiscourseNode } from "~/utils/getDiscourseNodes";
2222
import type { Result } from "~/utils/types";
2323
import internalError from "~/utils/internalError";
2424
import getDiscourseNodes from "~/utils/getDiscourseNodes";
25-
import { getFeatureFlag } from "~/components/settings/utils/accessors";
25+
import { useFeatureFlag } from "~/components/settings/utils/hooks";
2626

2727
export type CreateRelationDialogProps = {
2828
onClose: () => void;
@@ -373,7 +373,7 @@ export const renderCreateRelationDialog = (
373373
export const CreateRelationButton = (
374374
props: CreateRelationDialogProps,
375375
): React.JSX.Element | null => {
376-
const showAddRelation = getFeatureFlag("Reified Relation Triples");
376+
const showAddRelation = useFeatureFlag("Reified Relation Triples");
377377
if (!showAddRelation) return null;
378378
let extProps: ExtendedCreateRelationDialogProps | null = null;
379379
try {

apps/roam/src/components/results-view/ResultsTable.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { ContextContent } from "~/components/DiscourseContext";
2323
import DiscourseContextOverlay from "~/components/DiscourseContextOverlay";
2424
import { CONTEXT_OVERLAY_SUGGESTION } from "~/utils/predefinedSelections";
2525
import { strictQueryForReifiedBlocks } from "~/utils/createReifiedBlock";
26-
import { getFeatureFlag } from "~/components/settings/utils/accessors";
26+
import { useFeatureFlag } from "~/components/settings/utils/hooks";
2727

2828
const EXTRA_ROW_TYPES = ["context", "discourse"] as const;
2929
type ExtraRowType = (typeof EXTRA_ROW_TYPES)[number] | null;
@@ -205,7 +205,7 @@ const ResultRow = ({
205205
onDragEnd,
206206
onRefresh,
207207
}: ResultRowProps) => {
208-
const useReifiedRel = getFeatureFlag("Reified Relation Triples");
208+
const useReifiedRel = useFeatureFlag("Reified Relation Triples");
209209
const cell = (key: string) => {
210210
const value = toCellValue({
211211
value: r[`${key}-display`] || r[key] || "",

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

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useEffect, useMemo, useRef } from "react";
1+
import React, { useState, useEffect, useRef } from "react";
22
import {
33
Button,
44
Checkbox,
@@ -31,7 +31,7 @@ import { DGSupabaseClient } from "@repo/database/lib/client";
3131
import internalError from "~/utils/internalError";
3232
import SuggestiveModeSettings from "./SuggestiveModeSettings";
3333
import { BlockPropFeatureFlagPanel } from "./components/BlockPropFeatureFlagPanel";
34-
import { getFeatureFlag } from "./utils/accessors";
34+
import { useFeatureFlag } from "./utils/hooks";
3535

3636
const NodeRow = ({ node }: { node: PConceptFull }) => {
3737
return (
@@ -256,7 +256,7 @@ const MigrationTab = (): React.ReactElement => {
256256
const [useMigrationResults, setMigrationResults] = useState<string>("");
257257
const [useOngoing, setOngoing] = useState<boolean>(false);
258258
const [useDryRun, setDryRun] = useState<boolean>(false);
259-
const enabled = getFeatureFlag("Reified Relation Triples");
259+
const enabled = useFeatureFlag("Reified Relation Triples");
260260
const doMigrateRelations = async () => {
261261
setOngoing(true);
262262
try {
@@ -375,23 +375,18 @@ const FeatureFlagsTab = (): React.ReactElement => {
375375

376376
<Alert
377377
isOpen={isInstructionOpen}
378-
onConfirm={() => window.location.reload()}
378+
onConfirm={() => setIsInstructionOpen(false)}
379379
onCancel={() => setIsInstructionOpen(false)}
380-
confirmButtonText="Reload Graph"
381-
cancelButtonText="Later"
380+
confirmButtonText="Got it"
382381
intent={Intent.PRIMARY}
383382
>
384383
<p>
385384
If this is the first time enabling it, you will need to generate and
386385
upload all node embeddings to supabase.
387386
</p>
388387
<p>
389-
Please reload the graph to see the new &apos;Suggestive Mode&apos;
390-
tab.
391-
</p>
392-
<p>
393-
Then go to Suggestive Mode{" "}
394-
{"-> Sync Config -> Click on 'Generate & Upload All Node Embeddings'"}
388+
Go to the new &apos;Suggestive Mode&apos; tab, then Sync Config{" "}
389+
{"-> Click on 'Generate & Upload All Node Embeddings'"}
395390
</p>
396391
</Alert>
397392

@@ -422,10 +417,7 @@ const FeatureFlagsTab = (): React.ReactElement => {
422417

423418
const AdminPanel = (): React.ReactElement => {
424419
const [selectedTabId, setSelectedTabId] = useState<TabId>("admin");
425-
const suggestiveModeEnabled = useMemo(
426-
() => getFeatureFlag("Suggestive Mode Enabled"),
427-
[],
428-
);
420+
const suggestiveModeEnabled = useFeatureFlag("Suggestive Mode Enabled");
429421

430422
return (
431423
<Tabs

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

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import React, { useMemo, useState } from "react";
1+
import React, { useMemo } from "react";
22
import TextPanel from "roamjs-components/components/ConfigPanels/TextPanel";
33
import { getFormattedConfigTree } from "~/utils/discourseConfigRef";
44
import refreshConfigTree from "~/utils/refreshConfigTree";
55
import { DEFAULT_CANVAS_PAGE_FORMAT } from "~/index";
6-
import { Alert, Intent } from "@blueprintjs/core";
76
import { BlockPropFeatureFlagPanel } from "./components/BlockPropFeatureFlagPanel";
87

98
const DiscourseGraphHome = () => {
@@ -12,8 +11,6 @@ const DiscourseGraphHome = () => {
1211
return getFormattedConfigTree();
1312
}, []);
1413

15-
const [isAlertOpen, setIsAlertOpen] = useState(false);
16-
1714
return (
1815
<div className="flex flex-col gap-4 p-1">
1916
<TextPanel
@@ -37,23 +34,7 @@ const DiscourseGraphHome = () => {
3734
title="(BETA) Enable Left Sidebar"
3835
description="Whether or not to enable the left sidebar."
3936
featureKey="Enable Left Sidebar"
40-
onAfterChange={(checked) => {
41-
if (checked) {
42-
setIsAlertOpen(true);
43-
}
44-
}}
4537
/>
46-
<Alert
47-
isOpen={isAlertOpen}
48-
onConfirm={() => window.location.reload()}
49-
onCancel={() => setIsAlertOpen(false)}
50-
confirmButtonText="Reload Graph"
51-
cancelButtonText="Later"
52-
intent={Intent.PRIMARY}
53-
>
54-
<p>Enabling the Left Sidebar requires a graph reload to take effect.</p>
55-
<p>Would you like to reload now?</p>
56-
</Alert>
5738
</div>
5839
);
5940
};

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useMemo } from "react";
1+
import React from "react";
22
import { OnloadArgs } from "roamjs-components/types";
33
import { Label, Checkbox } from "@blueprintjs/core";
44
import Description from "roamjs-components/components/Description";
@@ -27,12 +27,12 @@ import internalError from "~/utils/internalError";
2727
import KeyboardShortcutInput from "./KeyboardShortcutInput";
2828
import { getSetting, setSetting } from "~/utils/extensionSettings";
2929
import streamlineStyling from "~/styles/streamlineStyling";
30-
import { getFeatureFlag } from "./utils/accessors";
30+
import { useFeatureFlag } from "./utils/hooks";
3131

3232
const HomePersonalSettings = ({ onloadArgs }: { onloadArgs: OnloadArgs }) => {
3333
const extensionAPI = onloadArgs.extensionAPI;
3434
const overlayHandler = getOverlayHandler(onloadArgs);
35-
const suggestiveModeEnabled = useMemo(() => getFeatureFlag("Suggestive Mode Enabled"), []);
35+
const suggestiveModeEnabled = useFeatureFlag("Suggestive Mode Enabled");
3636

3737
return (
3838
<div className="flex flex-col gap-4 p-1">

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import React, {
33
useCallback,
44
useRef,
55
useEffect,
6-
useMemo,
76
} from "react";
87
import { DiscourseNode } from "~/utils/getDiscourseNodes";
98
import FlagPanel from "roamjs-components/components/ConfigPanels/FlagPanel";
@@ -29,7 +28,7 @@ import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByPar
2928
import createBlock from "roamjs-components/writes/createBlock";
3029
import updateBlock from "roamjs-components/writes/updateBlock";
3130
import DiscourseNodeSuggestiveRules from "./DiscourseNodeSuggestiveRules";
32-
import { getFeatureFlag } from "./utils/accessors";
31+
import { useFeatureFlag } from "./utils/hooks";
3332
import refreshConfigTree from "~/utils/refreshConfigTree";
3433

3534
export const getCleanTagText = (tag: string): string => {
@@ -172,7 +171,7 @@ const NodeConfig = ({
172171
node: DiscourseNode;
173172
onloadArgs: OnloadArgs;
174173
}) => {
175-
const suggestiveModeEnabled = useMemo(() => getFeatureFlag("Suggestive Mode Enabled"), []);
174+
const suggestiveModeEnabled = useFeatureFlag("Suggestive Mode Enabled");
176175
const getUid = (key: string) =>
177176
getSubTree({
178177
parentUid: node.type,
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { useState, useEffect } from "react";
2+
import { getFeatureFlag } from "./accessors";
3+
import type { FeatureFlags } from "./zodSchema";
4+
5+
const FEATURE_FLAG_CHANGE_EVENT = "discourse-graph:feature-flag-change";
6+
7+
type FeatureFlagChangeDetail = {
8+
key: keyof FeatureFlags;
9+
value: boolean;
10+
};
11+
12+
export const emitFeatureFlagChange = (
13+
key: keyof FeatureFlags,
14+
value: boolean,
15+
): void => {
16+
window.dispatchEvent(
17+
new CustomEvent<FeatureFlagChangeDetail>(FEATURE_FLAG_CHANGE_EVENT, {
18+
detail: { key, value },
19+
}),
20+
);
21+
};
22+
23+
export const useFeatureFlag = (key: keyof FeatureFlags): boolean => {
24+
const [value, setValue] = useState(() => getFeatureFlag(key));
25+
26+
useEffect(() => {
27+
const handleChange = (event: Event) => {
28+
const customEvent = event as CustomEvent<FeatureFlagChangeDetail>;
29+
if (customEvent.detail.key === key) {
30+
setValue(customEvent.detail.value);
31+
}
32+
};
33+
34+
window.addEventListener(FEATURE_FLAG_CHANGE_EVENT, handleChange);
35+
return () => {
36+
window.removeEventListener(FEATURE_FLAG_CHANGE_EVENT, handleChange);
37+
};
38+
}, [key]);
39+
40+
return value;
41+
};

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

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,15 @@ import {
1414
type PersonalSettings,
1515
type DiscourseNodeSettings,
1616
} from "./zodSchema";
17-
import { render as renderToast } from "roamjs-components/components/Toast";
1817
import {
1918
unmountLeftSidebar,
2019
remountLeftSidebar,
2120
} from "~/components/LeftSidebarView";
21+
import {
22+
initializeSupabaseSync,
23+
setSyncActivity,
24+
} from "~/utils/syncDgNodesToSupabase";
25+
import { emitFeatureFlagChange } from "./hooks";
2226

2327
type PullWatchCallback = (before: unknown, after: unknown) => void;
2428

@@ -102,6 +106,7 @@ export const featureFlagHandlers: Partial<
102106
> = {
103107
"Enable Left Sidebar": (newValue, oldValue) => {
104108
if (newValue !== oldValue) {
109+
emitFeatureFlagChange("Enable Left Sidebar", newValue);
105110
if (newValue) {
106111
void remountLeftSidebar();
107112
} else {
@@ -111,22 +116,17 @@ export const featureFlagHandlers: Partial<
111116
},
112117
"Suggestive Mode Enabled": (newValue, oldValue) => {
113118
if (newValue !== oldValue) {
114-
renderToast({
115-
id: "suggestive-mode-changed",
116-
content: `Suggestive Mode ${newValue ? "enabled" : "disabled"}. Please reload the graph for changes to take effect.`,
117-
intent: "primary",
118-
timeout: 5000,
119-
});
119+
emitFeatureFlagChange("Suggestive Mode Enabled", newValue);
120+
if (newValue) {
121+
initializeSupabaseSync();
122+
} else {
123+
setSyncActivity(false);
124+
}
120125
}
121126
},
122127
"Reified Relation Triples": (newValue, oldValue) => {
123128
if (newValue !== oldValue) {
124-
renderToast({
125-
id: "reified-relations-changed",
126-
content: `Reified Relation Triples ${newValue ? "enabled" : "disabled"}. Please reload the graph for changes to take effect.`,
127-
intent: "primary",
128-
timeout: 5000,
129-
});
129+
emitFeatureFlagChange("Reified Relation Triples", newValue);
130130
}
131131
},
132132
};

apps/roam/src/index.ts

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,15 @@ 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 { getSetting } from "./utils/extensionSettings";
3935
import { initPostHog } from "./utils/posthog";
4036
import {
4137
STREAMLINE_STYLING_KEY,
4238
DISALLOW_DIAGNOSTICS,
4339
} from "./data/userSettings";
4440
import { initSchema } from "./components/settings/utils/init";
41+
import { setupPullWatchSettings } from "./components/settings/utils/pullWatchers";
42+
import { getFeatureFlag } from "./components/settings/utils/accessors";
4543

4644
export const DEFAULT_CANVAS_PAGE_FORMAT = "Canvas/*";
4745

@@ -76,8 +74,8 @@ export default runExtension(async (onloadArgs) => {
7674

7775
initPluginTimer();
7876

79-
// For testing purposes
80-
await initSchema();
77+
const { blockUids } = await initSchema();
78+
const cleanupPullWatch = setupPullWatchSettings(blockUids);
8179
addGraphViewNodeStyling();
8280
registerCommandPaletteCommands(onloadArgs);
8381
createSettingsPanel(onloadArgs);
@@ -111,14 +109,9 @@ export default runExtension(async (onloadArgs) => {
111109
document.addEventListener("input", discourseNodeSearchTriggerListener);
112110
document.addEventListener("selectionchange", nodeCreationPopoverListener);
113111

114-
const isSuggestiveModeEnabled = getUidAndBooleanSetting({
115-
tree: getBasicTreeByParentUid(
116-
getPageUidByPageTitle(DISCOURSE_CONFIG_PAGE_TITLE),
117-
),
118-
text: "(BETA) Suggestive Mode Enabled",
119-
}).value;
120-
121-
if (isSuggestiveModeEnabled) {
112+
// Initialize sync if suggestive mode was already enabled before plugin load
113+
// (pull watcher handles reactive changes after this)
114+
if (getFeatureFlag("Suggestive Mode Enabled")) {
122115
initializeSupabaseSync();
123116
}
124117

@@ -164,6 +157,7 @@ export default runExtension(async (onloadArgs) => {
164157
],
165158
observers: observers,
166159
unload: () => {
160+
cleanupPullWatch();
167161
setSyncActivity(false);
168162
window.roamjs.extension?.smartblocks?.unregisterCommand("QUERYBUILDER");
169163
// @ts-expect-error - tldraw throws a warning on multiple loads

apps/roam/src/utils/discourseConfigRef.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import {
44
StringSetting,
55
ExportConfigWithUids,
66
getUidAndStringSetting,
7-
getUidAndBooleanSetting,
8-
BooleanSetting,
97
} from "./getExportSettings";
108
import { DISCOURSE_CONFIG_PAGE_TITLE } from "~/utils/renderNodeConfigPage";
119
import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTitle";
@@ -44,8 +42,6 @@ type FormattedConfigTree = {
4442
canvasPageFormat: StringSetting;
4543
suggestiveMode: SuggestiveModeConfigWithUids;
4644
leftSidebar: LeftSidebarConfig;
47-
leftSidebarEnabled: BooleanSetting;
48-
suggestiveModeEnabled: BooleanSetting;
4945
};
5046

5147
export const getFormattedConfigTree = (): FormattedConfigTree => {
@@ -74,14 +70,6 @@ export const getFormattedConfigTree = (): FormattedConfigTree => {
7470
}),
7571
suggestiveMode: getSuggestiveModeConfigAndUids(configTreeRef.tree),
7672
leftSidebar: getLeftSidebarSettings(configTreeRef.tree),
77-
leftSidebarEnabled: getUidAndBooleanSetting({
78-
tree: configTreeRef.tree,
79-
text: "(BETA) Left Sidebar",
80-
}),
81-
suggestiveModeEnabled: getUidAndBooleanSetting({
82-
tree: configTreeRef.tree,
83-
text: "(BETA) Suggestive Mode Enabled",
84-
}),
8573
};
8674
};
8775
export default configTreeRef;

0 commit comments

Comments
 (0)