From 08b3adf7cba4b879ea5b6ef669aa7749fc75f22b Mon Sep 17 00:00:00 2001 From: sid597 Date: Sun, 11 Jan 2026 23:56:46 +0530 Subject: [PATCH 1/6] new checkbox component for feature flag get and set in props, migrate to block prop based settings --- .../src/components/settings/AdminPanel.tsx | 116 ++++++------------ .../settings/BlockPropFeatureFlagPanel.tsx | 48 ++++++++ .../components/settings/GeneralSettings.tsx | 21 ++-- 3 files changed, 92 insertions(+), 93 deletions(-) create mode 100644 apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx diff --git a/apps/roam/src/components/settings/AdminPanel.tsx b/apps/roam/src/components/settings/AdminPanel.tsx index a4612ef5d..c309de2e6 100644 --- a/apps/roam/src/components/settings/AdminPanel.tsx +++ b/apps/roam/src/components/settings/AdminPanel.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useMemo } from "react"; +import React, { useState, useEffect, useMemo, useRef } from "react"; import { Button, Checkbox, @@ -12,9 +12,7 @@ import { TabId, Tabs, } from "@blueprintjs/core"; -import Description from "roamjs-components/components/Description"; import { Select } from "@blueprintjs/select"; -import { getSetting, setSetting } from "~/utils/extensionSettings"; import { getSupabaseContext, getLoggedInClient, @@ -32,11 +30,8 @@ import { countReifiedRelations } from "~/utils/createReifiedBlock"; import type { DGSupabaseClient } from "@repo/database/lib/client"; import internalError from "~/utils/internalError"; import SuggestiveModeSettings from "./SuggestiveModeSettings"; -import { getFormattedConfigTree } from "~/utils/discourseConfigRef"; -import refreshConfigTree from "~/utils/refreshConfigTree"; -import createBlock from "roamjs-components/writes/createBlock"; -import deleteBlock from "roamjs-components/writes/deleteBlock"; -import { USE_REIFIED_RELATIONS } from "~/data/userSettings"; +import { BlockPropFeatureFlagPanel } from "./BlockPropFeatureFlagPanel"; +import { getFeatureFlag } from "./utils/accessors"; const NodeRow = ({ node }: { node: PConceptFull }) => { return ( @@ -261,7 +256,7 @@ const MigrationTab = (): React.ReactElement => { const [useMigrationResults, setMigrationResults] = useState(""); const [useOngoing, setOngoing] = useState(false); const [useDryRun, setDryRun] = useState(false); - const enabled = getSetting(USE_REIFIED_RELATIONS, false); + const enabled = getFeatureFlag("Reified Relation Triples"); const doMigrateRelations = async () => { setOngoing(true); try { @@ -331,64 +326,40 @@ const MigrationTab = (): React.ReactElement => { }; const FeatureFlagsTab = (): React.ReactElement => { - const [useReifiedRelations, setUseReifiedRelations] = useState( - getSetting(USE_REIFIED_RELATIONS, false), - ); - const settings = useMemo(() => { - refreshConfigTree(); - return getFormattedConfigTree(); - }, []); - - const [suggestiveModeEnabled, setSuggestiveModeEnabled] = useState( - settings.suggestiveModeEnabled.value || false, - ); - const [suggestiveModeUid, setSuggestiveModeUid] = useState( - settings.suggestiveModeEnabled.uid, - ); const [isAlertOpen, setIsAlertOpen] = useState(false); const [isInstructionOpen, setIsInstructionOpen] = useState(false); + const confirmResolverRef = useRef<((value: boolean) => void) | null>(null); + + const handleSuggestiveModeBeforeEnable = (): Promise => { + return new Promise((resolve) => { + confirmResolverRef.current = resolve; + setIsAlertOpen(true); + }); + }; return (
- { - const checked = (e.target as HTMLInputElement).checked; - if (checked) { - setIsAlertOpen(true); - } else { - if (suggestiveModeUid) { - void deleteBlock(suggestiveModeUid); - setSuggestiveModeUid(undefined); - } - setSuggestiveModeEnabled(false); - } + { + if (checked) setIsInstructionOpen(true); }} - labelElement={ - <> - (BETA) Suggestive Mode Enabled - Sync Config -> Click on 'Generate & Upload All Node Embeddings'" - } - /> - - } /> { - void createBlock({ - parentUid: settings.settingsUid, - node: { text: "(BETA) Suggestive Mode Enabled" }, - }).then((uid) => { - setSuggestiveModeUid(uid); - setSuggestiveModeEnabled(true); - setIsAlertOpen(false); - setIsInstructionOpen(true); - }); + confirmResolverRef.current?.(true); + confirmResolverRef.current = null; + setIsAlertOpen(false); + }} + onCancel={() => { + confirmResolverRef.current?.(false); + confirmResolverRef.current = null; + setIsAlertOpen(false); }} - onCancel={() => setIsAlertOpen(false)} canEscapeKeyCancel={true} canOutsideClickCancel={true} intent={Intent.PRIMARY} @@ -424,25 +395,10 @@ const FeatureFlagsTab = (): React.ReactElement => {

- { - const target = e.target as HTMLInputElement; - setUseReifiedRelations(target.checked); - void setSetting(USE_REIFIED_RELATIONS, target.checked).catch( - () => undefined, - ); - }} - labelElement={ - <> - Reified Relation Triples - - - } +
} /> - {settings.suggestiveModeEnabled.value && ( + {suggestiveModeEnabled && ( Promise; + onAfterChange?: (checked: boolean) => void; +}) => { + const [value, setValue] = useState(() => getFeatureFlag(featureKey)); + + const handleChange = async (e: React.ChangeEvent) => { + const { checked } = e.target; + + if (checked && onBeforeEnable) { + const shouldProceed = await onBeforeEnable(); + if (!shouldProceed) return; + } + + setFeatureFlag(featureKey, checked); + setValue(checked); + onAfterChange?.(checked); + }; + + return ( + void handleChange(e)} + labelElement={ + <> + {idToTitle(title)} + + + } + /> + ); +}; diff --git a/apps/roam/src/components/settings/GeneralSettings.tsx b/apps/roam/src/components/settings/GeneralSettings.tsx index 3270ef616..da0ea6283 100644 --- a/apps/roam/src/components/settings/GeneralSettings.tsx +++ b/apps/roam/src/components/settings/GeneralSettings.tsx @@ -1,10 +1,10 @@ import React, { useMemo, useState } from "react"; import TextPanel from "roamjs-components/components/ConfigPanels/TextPanel"; -import FlagPanel from "roamjs-components/components/ConfigPanels/FlagPanel"; import { getFormattedConfigTree } from "~/utils/discourseConfigRef"; import refreshConfigTree from "~/utils/refreshConfigTree"; import { DEFAULT_CANVAS_PAGE_FORMAT } from "~/index"; import { Alert, Intent } from "@blueprintjs/core"; +import { BlockPropFeatureFlagPanel } from "./BlockPropFeatureFlagPanel"; const DiscourseGraphHome = () => { const settings = useMemo(() => { @@ -33,19 +33,14 @@ const DiscourseGraphHome = () => { value={settings.canvasPageFormat.value} defaultValue={DEFAULT_CANVAS_PAGE_FORMAT} /> - { - if (checked) { - setIsAlertOpen(true); - } - }, + featureKey="Enable Left Sidebar" + onAfterChange={(checked) => { + if (checked) { + setIsAlertOpen(true); + } }} /> Date: Mon, 12 Jan 2026 00:03:39 +0530 Subject: [PATCH 2/6] use getFeatureFlag() --- apps/roam/src/components/CreateRelationDialog.tsx | 5 ++--- apps/roam/src/components/SuggestionsBody.tsx | 5 ++--- .../DiscourseRelationUtil.tsx | 5 ++--- .../src/components/results-view/ResultsTable.tsx | 5 ++--- .../components/settings/HomePersonalSettings.tsx | 6 +++--- apps/roam/src/components/settings/NodeConfig.tsx | 9 +++------ .../src/utils/initializeObserversAndListeners.ts | 13 +++---------- apps/roam/src/utils/migrateRelations.ts | 9 ++++----- .../utils/registerDiscourseDatalogTranslators.ts | 8 ++------ 9 files changed, 23 insertions(+), 42 deletions(-) diff --git a/apps/roam/src/components/CreateRelationDialog.tsx b/apps/roam/src/components/CreateRelationDialog.tsx index d880bf0fe..5618a2f27 100644 --- a/apps/roam/src/components/CreateRelationDialog.tsx +++ b/apps/roam/src/components/CreateRelationDialog.tsx @@ -12,7 +12,6 @@ import { render as renderToast } from "roamjs-components/components/Toast"; import MenuItemSelect from "roamjs-components/components/MenuItemSelect"; import AutocompleteInput from "roamjs-components/components/AutocompleteInput"; import getPageTitleByPageUid from "roamjs-components/queries/getPageTitleByPageUid"; -import { getSetting } from "~/utils/extensionSettings"; import getDiscourseRelations, { type DiscourseRelation, } from "~/utils/getDiscourseRelations"; @@ -23,7 +22,7 @@ import type { DiscourseNode } from "~/utils/getDiscourseNodes"; import type { Result } from "~/utils/types"; import internalError from "~/utils/internalError"; import getDiscourseNodes from "~/utils/getDiscourseNodes"; -import { USE_REIFIED_RELATIONS } from "~/data/userSettings"; +import { getFeatureFlag } from "~/components/settings/utils/accessors"; export type CreateRelationDialogProps = { onClose: () => void; @@ -379,7 +378,7 @@ export const renderCreateRelationDialog = ( export const CreateRelationButton = ( props: CreateRelationDialogProps, ): React.JSX.Element | null => { - const showAddRelation = getSetting(USE_REIFIED_RELATIONS, false); + const showAddRelation = getFeatureFlag("Reified Relation Triples"); if (!showAddRelation) return null; let extProps: ExtendedCreateRelationDialogProps | null = null; try { diff --git a/apps/roam/src/components/SuggestionsBody.tsx b/apps/roam/src/components/SuggestionsBody.tsx index 89cf7f7c9..1e84ec839 100644 --- a/apps/roam/src/components/SuggestionsBody.tsx +++ b/apps/roam/src/components/SuggestionsBody.tsx @@ -26,9 +26,8 @@ import normalizePageTitle from "roamjs-components/queries/normalizePageTitle"; import { type RelationDetails } from "~/utils/hyde"; import { getFormattedConfigTree } from "~/utils/discourseConfigRef"; import { render as renderToast } from "roamjs-components/components/Toast"; -import { getSetting } from "~/utils/extensionSettings"; -import { USE_REIFIED_RELATIONS } from "~/data/userSettings"; import { createReifiedRelation } from "~/utils/createReifiedBlock"; +import { getFeatureFlag } from "~/components/settings/utils/accessors"; export type DiscourseData = { results: Awaited>; @@ -309,7 +308,7 @@ const SuggestionsBody = ({ }; const handleCreateBlock = async (node: SuggestedNode) => { - if (getSetting(USE_REIFIED_RELATIONS, false)) { + if (getFeatureFlag("Reified Relation Triples")) { if (discourseNode === false) { renderToast({ id: "suggestions-create-block-error", diff --git a/apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationUtil.tsx b/apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationUtil.tsx index f5b4e6c02..ef3fc767a 100644 --- a/apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationUtil.tsx +++ b/apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationUtil.tsx @@ -63,7 +63,6 @@ import { shapeAtTranslationStart, updateArrowTerminal, } from "./helpers"; -import { getSetting } from "~/utils/extensionSettings"; import { createReifiedRelation } from "~/utils/createReifiedBlock"; import { discourseContext, isPageUid } from "~/components/canvas/Tldraw"; import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTitle"; @@ -81,7 +80,7 @@ import getPageTitleByPageUid from "roamjs-components/queries/getPageTitleByPageU import { AddReferencedNodeType } from "./DiscourseRelationTool"; import { dispatchToastEvent } from "~/components/canvas/ToastListener"; import internalError from "~/utils/internalError"; -import { USE_REIFIED_RELATIONS } from "~/data/userSettings"; +import { getFeatureFlag } from "~/components/settings/utils/accessors"; const COLOR_ARRAY = Array.from(textShapeProps.color.values) .filter((c) => !["red", "green", "grey"].includes(c)) @@ -612,7 +611,7 @@ export const createAllRelationShapeUtils = ( if (arrow.type !== target.type) { editor.updateShapes([{ id: arrow.id, type: target.type }]); } - if (getSetting(USE_REIFIED_RELATIONS, false)) { + if (getFeatureFlag("Reified Relation Triples")) { const sourceAsDNS = asDiscourseNodeShape(source, editor); const targetAsDNS = asDiscourseNodeShape(target, editor); diff --git a/apps/roam/src/components/results-view/ResultsTable.tsx b/apps/roam/src/components/results-view/ResultsTable.tsx index 3dba01e10..c0f158b49 100644 --- a/apps/roam/src/components/results-view/ResultsTable.tsx +++ b/apps/roam/src/components/results-view/ResultsTable.tsx @@ -22,10 +22,9 @@ import toCellValue from "~/utils/toCellValue"; import { ContextContent } from "~/components/DiscourseContext"; import DiscourseContextOverlay from "~/components/DiscourseContextOverlay"; import { CONTEXT_OVERLAY_SUGGESTION } from "~/utils/predefinedSelections"; -import { USE_REIFIED_RELATIONS } from "~/data/userSettings"; -import { getSetting } from "~/utils/extensionSettings"; import { strictQueryForReifiedBlocks } from "~/utils/createReifiedBlock"; import internalError from "~/utils/internalError"; +import { getFeatureFlag } from "~/components/settings/utils/accessors"; const EXTRA_ROW_TYPES = ["context", "discourse"] as const; type ExtraRowType = (typeof EXTRA_ROW_TYPES)[number] | null; @@ -263,7 +262,7 @@ const ResultRow = ({ onDragEnd, onRefresh, }: ResultRowProps) => { - const useReifiedRel = getSetting(USE_REIFIED_RELATIONS, false); + const useReifiedRel = getFeatureFlag("Reified Relation Triples"); const cell = (key: string) => { const value = toCellValue({ value: r[`${key}-display`] || r[key] || "", diff --git a/apps/roam/src/components/settings/HomePersonalSettings.tsx b/apps/roam/src/components/settings/HomePersonalSettings.tsx index 1bc1b4b71..c48414850 100644 --- a/apps/roam/src/components/settings/HomePersonalSettings.tsx +++ b/apps/roam/src/components/settings/HomePersonalSettings.tsx @@ -27,12 +27,12 @@ import internalError from "~/utils/internalError"; import KeyboardShortcutInput from "./KeyboardShortcutInput"; import { getSetting, setSetting } from "~/utils/extensionSettings"; import streamlineStyling from "~/styles/streamlineStyling"; -import { getFormattedConfigTree } from "~/utils/discourseConfigRef"; +import { getFeatureFlag } from "./utils/accessors"; const HomePersonalSettings = ({ onloadArgs }: { onloadArgs: OnloadArgs }) => { const extensionAPI = onloadArgs.extensionAPI; const overlayHandler = getOverlayHandler(onloadArgs); - const settings = useMemo(() => getFormattedConfigTree(), []); + const suggestiveModeEnabled = useMemo(() => getFeatureFlag("Suggestive Mode Enabled"), []); return (
@@ -85,7 +85,7 @@ const HomePersonalSettings = ({ onloadArgs }: { onloadArgs: OnloadArgs }) => { } /> - {settings.suggestiveModeEnabled?.value && ( + {suggestiveModeEnabled && ( { @@ -172,10 +172,7 @@ const NodeConfig = ({ node: DiscourseNode; onloadArgs: OnloadArgs; }) => { - const settings = useMemo(() => { - refreshConfigTree(); - return getFormattedConfigTree(); - }, []); + const suggestiveModeEnabled = useMemo(() => getFeatureFlag("Suggestive Mode Enabled"), []); const getUid = (key: string) => getSubTree({ parentUid: node.type, @@ -438,7 +435,7 @@ const NodeConfig = ({
} /> - {settings.suggestiveModeEnabled.value && ( + {suggestiveModeEnabled && ( { void (async () => { - const isLeftSidebarEnabled = getUidAndBooleanSetting({ - tree: configTree, - text: "(BETA) Left Sidebar", - }).value; + const isLeftSidebarEnabled = getFeatureFlag("Enable Left Sidebar"); const container = el as HTMLDivElement; if (isLeftSidebarEnabled) { container.style.padding = "0"; diff --git a/apps/roam/src/utils/migrateRelations.ts b/apps/roam/src/utils/migrateRelations.ts index 41cba8014..4ccf0cd06 100644 --- a/apps/roam/src/utils/migrateRelations.ts +++ b/apps/roam/src/utils/migrateRelations.ts @@ -2,20 +2,19 @@ import getRelationData from "./getRelationData"; import getBlockProps from "./getBlockProps"; import type { json } from "./getBlockProps"; import setBlockProps from "./setBlockProps"; -import { getSetting, setSetting } from "./extensionSettings"; -import { USE_REIFIED_RELATIONS } from "~/data/userSettings"; import { createReifiedRelation, DISCOURSE_GRAPH_PROP_NAME, } from "./createReifiedBlock"; +import { getFeatureFlag, setFeatureFlag } from "~/components/settings/utils/accessors"; const MIGRATION_PROP_NAME = "relation-migration"; const migrateRelations = async (dryRun = false): Promise => { - const authorized = getSetting(USE_REIFIED_RELATIONS, false); + const authorized = getFeatureFlag("Reified Relation Triples"); if (!authorized) return 0; let numProcessed = 0; - await setSetting(USE_REIFIED_RELATIONS, false); // so queries use patterns + setFeatureFlag("Reified Relation Triples", false); // so queries use patterns // wait for the settings to propagate await new Promise((resolve) => setTimeout(resolve, 150)); try { @@ -65,7 +64,7 @@ const migrateRelations = async (dryRun = false): Promise => { numProcessed++; } } finally { - await setSetting(USE_REIFIED_RELATIONS, true); + setFeatureFlag("Reified Relation Triples", true); } return numProcessed; }; diff --git a/apps/roam/src/utils/registerDiscourseDatalogTranslators.ts b/apps/roam/src/utils/registerDiscourseDatalogTranslators.ts index f7528c415..59bdd3e36 100644 --- a/apps/roam/src/utils/registerDiscourseDatalogTranslators.ts +++ b/apps/roam/src/utils/registerDiscourseDatalogTranslators.ts @@ -19,9 +19,8 @@ import replaceDatalogVariables from "./replaceDatalogVariables"; import parseQuery from "./parseQuery"; import { fireQuerySync, getWhereClauses } from "./fireQuery"; import { toVar } from "./compileDatalog"; -import { getSetting } from "./extensionSettings"; import { getExistingRelationPageUid } from "./createReifiedBlock"; -import { USE_REIFIED_RELATIONS } from "~/data/userSettings"; +import { getFeatureFlag } from "~/components/settings/utils/accessors"; const hasTag = (node: DiscourseNode): node is DiscourseNode & { tag: string } => !!node.tag; @@ -410,10 +409,7 @@ const registerDiscourseDatalogTranslators = () => { registerDatalogTranslator({ key: label, callback: ({ source, target, uid }) => { - const useReifiedRelations = getSetting( - USE_REIFIED_RELATIONS, - false, - ); + const useReifiedRelations = getFeatureFlag("Reified Relation Triples"); const relationPageUid = getExistingRelationPageUid(); const filteredRelations = getFilteredRelations({ From ba1773d77446334c025676d4268e368c8a7e1954 Mon Sep 17 00:00:00 2001 From: sid597 Date: Mon, 12 Jan 2026 00:16:04 +0530 Subject: [PATCH 3/6] rerender left sidebar on enable/disable --- apps/roam/src/components/LeftSidebarView.tsx | 28 +++++++++++ .../components/settings/utils/pullWatchers.ts | 47 +++++++++++++++++-- .../utils/initializeObserversAndListeners.ts | 4 +- 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/apps/roam/src/components/LeftSidebarView.tsx b/apps/roam/src/components/LeftSidebarView.tsx index 34ce369ca..5635c1d00 100644 --- a/apps/roam/src/components/LeftSidebarView.tsx +++ b/apps/roam/src/components/LeftSidebarView.tsx @@ -508,12 +508,20 @@ const migrateFavorites = async () => { refreshConfigTree(); }; +let cachedOnloadArgs: OnloadArgs | null = null; + +export const cacheOnloadArgs = (onloadArgs: OnloadArgs): void => { + cachedOnloadArgs = onloadArgs; +}; + export const mountLeftSidebar = async ( wrapper: HTMLElement, onloadArgs: OnloadArgs, ): Promise => { if (!wrapper) return; + cachedOnloadArgs = onloadArgs; + const id = "dg-left-sidebar-root"; let root = wrapper.querySelector(`#${id}`) as HTMLDivElement; if (!root) { @@ -531,4 +539,24 @@ export const mountLeftSidebar = async ( ReactDOM.render(, root); }; +export const unmountLeftSidebar = (): void => { + const wrapper = document.querySelector(".starred-pages-wrapper") as HTMLDivElement; + if (!wrapper) return; + + const root = wrapper.querySelector("#dg-left-sidebar-root") as HTMLDivElement; + if (root) { + ReactDOM.unmountComponentAtNode(root); + root.remove(); + } + wrapper.style.padding = ""; +}; + +export const remountLeftSidebar = async (): Promise => { + const wrapper = document.querySelector(".starred-pages-wrapper") as HTMLDivElement; + if (!wrapper || !cachedOnloadArgs) return; + + wrapper.style.padding = "0"; + await mountLeftSidebar(wrapper, cachedOnloadArgs); +}; + export default LeftSidebarView; diff --git a/apps/roam/src/components/settings/utils/pullWatchers.ts b/apps/roam/src/components/settings/utils/pullWatchers.ts index 9e84404fa..cdb51243f 100644 --- a/apps/roam/src/components/settings/utils/pullWatchers.ts +++ b/apps/roam/src/components/settings/utils/pullWatchers.ts @@ -12,6 +12,8 @@ import { type PersonalSettings, type DiscourseNodeSettings, } from "./zodSchema"; +import { render as renderToast } from "roamjs-components/components/Toast"; +import { unmountLeftSidebar, remountLeftSidebar } from "~/components/LeftSidebarView"; type PullWatchCallback = Parameters[2]; @@ -86,10 +88,47 @@ const addPullWatch = ( export const featureFlagHandlers: Partial< Record void> > = { - // Add handlers as needed: - // "Enable Left Sidebar": (newValue) => { ... }, - // "Suggestive Mode Enabled": (newValue) => { ... }, - // "Reified Relation Triples": (newValue) => { ... }, + "Enable Left Sidebar": (newValue, oldValue) => { + if (newValue !== oldValue) { + if (newValue) { + void remountLeftSidebar(); + renderToast({ + id: "left-sidebar-enabled", + content: "Left Sidebar enabled.", + intent: "success", + timeout: 3000, + }); + } else { + unmountLeftSidebar(); + renderToast({ + id: "left-sidebar-disabled", + content: "Left Sidebar disabled.", + intent: "primary", + timeout: 3000, + }); + } + } + }, + "Suggestive Mode Enabled": (newValue, oldValue) => { + if (newValue !== oldValue) { + renderToast({ + id: "suggestive-mode-changed", + content: `Suggestive Mode ${newValue ? "enabled" : "disabled"}. Please reload the graph for changes to take effect.`, + intent: "primary", + timeout: 5000, + }); + } + }, + "Reified Relation Triples": (newValue, oldValue) => { + if (newValue !== oldValue) { + renderToast({ + id: "reified-relations-changed", + content: `Reified Relation Triples ${newValue ? "enabled" : "disabled"}. Please reload the graph for changes to take effect.`, + intent: "primary", + timeout: 5000, + }); + } + }, }; type GlobalSettingsHandlers = { diff --git a/apps/roam/src/utils/initializeObserversAndListeners.ts b/apps/roam/src/utils/initializeObserversAndListeners.ts index d79e3ad6a..ef97f2865 100644 --- a/apps/roam/src/utils/initializeObserversAndListeners.ts +++ b/apps/roam/src/utils/initializeObserversAndListeners.ts @@ -49,7 +49,7 @@ import { renderNodeTagPopupButton } from "./renderNodeTagPopup"; import { renderImageToolsMenu } from "./renderImageToolsMenu"; import { formatHexColor } from "~/components/settings/DiscourseNodeCanvasSettings"; import { getSetting } from "./extensionSettings"; -import { mountLeftSidebar } from "~/components/LeftSidebarView"; +import { mountLeftSidebar, cacheOnloadArgs } from "~/components/LeftSidebarView"; import { getUidAndBooleanSetting } from "./getExportSettings"; import { getCleanTagText } from "~/components/settings/NodeConfig"; import { getFeatureFlag } from "~/components/settings/utils/accessors"; @@ -271,6 +271,8 @@ export const initObservers = async ({ className: "starred-pages-wrapper", callback: (el) => { void (async () => { + cacheOnloadArgs(onloadArgs); + const isLeftSidebarEnabled = getFeatureFlag("Enable Left Sidebar"); const container = el as HTMLDivElement; if (isLeftSidebarEnabled) { From c6b2937208917bcbb99a0aaea83b6ab474952da7 Mon Sep 17 00:00:00 2001 From: sid597 Date: Mon, 12 Jan 2026 13:15:04 +0530 Subject: [PATCH 4/6] fix component location --- .../src/components/settings/AdminPanel.tsx | 2 +- .../components/settings/GeneralSettings.tsx | 2 +- .../BlockPropFeatureFlagPanel.tsx | 4 ++-- .../components/settings/utils/pullWatchers.ts | 21 +++++++------------ 4 files changed, 11 insertions(+), 18 deletions(-) rename apps/roam/src/components/settings/{ => components}/BlockPropFeatureFlagPanel.tsx (90%) diff --git a/apps/roam/src/components/settings/AdminPanel.tsx b/apps/roam/src/components/settings/AdminPanel.tsx index c309de2e6..9ab4bb2c0 100644 --- a/apps/roam/src/components/settings/AdminPanel.tsx +++ b/apps/roam/src/components/settings/AdminPanel.tsx @@ -30,7 +30,7 @@ import { countReifiedRelations } from "~/utils/createReifiedBlock"; import type { DGSupabaseClient } from "@repo/database/lib/client"; import internalError from "~/utils/internalError"; import SuggestiveModeSettings from "./SuggestiveModeSettings"; -import { BlockPropFeatureFlagPanel } from "./BlockPropFeatureFlagPanel"; +import { BlockPropFeatureFlagPanel } from "./components/BlockPropFeatureFlagPanel"; import { getFeatureFlag } from "./utils/accessors"; const NodeRow = ({ node }: { node: PConceptFull }) => { diff --git a/apps/roam/src/components/settings/GeneralSettings.tsx b/apps/roam/src/components/settings/GeneralSettings.tsx index da0ea6283..9416a39bf 100644 --- a/apps/roam/src/components/settings/GeneralSettings.tsx +++ b/apps/roam/src/components/settings/GeneralSettings.tsx @@ -4,7 +4,7 @@ import { getFormattedConfigTree } from "~/utils/discourseConfigRef"; import refreshConfigTree from "~/utils/refreshConfigTree"; import { DEFAULT_CANVAS_PAGE_FORMAT } from "~/index"; import { Alert, Intent } from "@blueprintjs/core"; -import { BlockPropFeatureFlagPanel } from "./BlockPropFeatureFlagPanel"; +import { BlockPropFeatureFlagPanel } from "./components/BlockPropFeatureFlagPanel"; const DiscourseGraphHome = () => { const settings = useMemo(() => { diff --git a/apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx b/apps/roam/src/components/settings/components/BlockPropFeatureFlagPanel.tsx similarity index 90% rename from apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx rename to apps/roam/src/components/settings/components/BlockPropFeatureFlagPanel.tsx index c28a0ec1c..8e3669ded 100644 --- a/apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx +++ b/apps/roam/src/components/settings/components/BlockPropFeatureFlagPanel.tsx @@ -1,5 +1,5 @@ -import { getFeatureFlag, setFeatureFlag } from "./utils/accessors"; -import { type FeatureFlags } from "./utils/zodSchema"; +import { getFeatureFlag, setFeatureFlag } from "../utils/accessors"; +import { type FeatureFlags } from "../utils/zodSchema"; import { Checkbox } from "@blueprintjs/core"; import Description from "roamjs-components/components/Description"; import idToTitle from "roamjs-components/util/idToTitle"; diff --git a/apps/roam/src/components/settings/utils/pullWatchers.ts b/apps/roam/src/components/settings/utils/pullWatchers.ts index cdb51243f..51659846c 100644 --- a/apps/roam/src/components/settings/utils/pullWatchers.ts +++ b/apps/roam/src/components/settings/utils/pullWatchers.ts @@ -13,7 +13,10 @@ import { type DiscourseNodeSettings, } from "./zodSchema"; import { render as renderToast } from "roamjs-components/components/Toast"; -import { unmountLeftSidebar, remountLeftSidebar } from "~/components/LeftSidebarView"; +import { + unmountLeftSidebar, + remountLeftSidebar, +} from "~/components/LeftSidebarView"; type PullWatchCallback = Parameters[2]; @@ -85,6 +88,7 @@ const addPullWatch = ( }; + export const featureFlagHandlers: Partial< Record void> > = { @@ -92,20 +96,8 @@ export const featureFlagHandlers: Partial< if (newValue !== oldValue) { if (newValue) { void remountLeftSidebar(); - renderToast({ - id: "left-sidebar-enabled", - content: "Left Sidebar enabled.", - intent: "success", - timeout: 3000, - }); } else { unmountLeftSidebar(); - renderToast({ - id: "left-sidebar-disabled", - content: "Left Sidebar disabled.", - intent: "primary", - timeout: 3000, - }); } } }, @@ -233,6 +225,7 @@ export const setupPullWatchOnSettingsPage = ( newSettings, ); } + } } )); @@ -252,6 +245,7 @@ export const setupPullWatchOnSettingsPage = ( newSettings, ); } + } } )); @@ -260,7 +254,6 @@ export const setupPullWatchOnSettingsPage = ( return createCleanupFn(watches); }; - export const setupPullWatchDiscourseNodes = ( nodePageUids: Record, ): (() => void) => { From 42bce3a6666d57eab47e44cc485b186f4a356e98 Mon Sep 17 00:00:00 2001 From: sid597 Date: Mon, 12 Jan 2026 18:53:56 +0530 Subject: [PATCH 5/6] make feature flags fully reactive --- .../src/components/CreateRelationDialog.tsx | 4 +- .../components/results-view/ResultsTable.tsx | 4 +- .../src/components/settings/AdminPanel.tsx | 24 ++++------- .../components/settings/GeneralSettings.tsx | 21 +--------- .../settings/HomePersonalSettings.tsx | 6 +-- .../src/components/settings/NodeConfig.tsx | 5 +-- .../src/components/settings/utils/hooks.ts | 41 +++++++++++++++++++ .../components/settings/utils/pullWatchers.ts | 26 ++++++------ apps/roam/src/index.ts | 17 ++------ apps/roam/src/utils/discourseConfigRef.ts | 12 ------ 10 files changed, 76 insertions(+), 84 deletions(-) create mode 100644 apps/roam/src/components/settings/utils/hooks.ts diff --git a/apps/roam/src/components/CreateRelationDialog.tsx b/apps/roam/src/components/CreateRelationDialog.tsx index 5618a2f27..4d05f592b 100644 --- a/apps/roam/src/components/CreateRelationDialog.tsx +++ b/apps/roam/src/components/CreateRelationDialog.tsx @@ -22,7 +22,7 @@ import type { DiscourseNode } from "~/utils/getDiscourseNodes"; import type { Result } from "~/utils/types"; import internalError from "~/utils/internalError"; import getDiscourseNodes from "~/utils/getDiscourseNodes"; -import { getFeatureFlag } from "~/components/settings/utils/accessors"; +import { useFeatureFlag } from "~/components/settings/utils/hooks"; export type CreateRelationDialogProps = { onClose: () => void; @@ -378,7 +378,7 @@ export const renderCreateRelationDialog = ( export const CreateRelationButton = ( props: CreateRelationDialogProps, ): React.JSX.Element | null => { - const showAddRelation = getFeatureFlag("Reified Relation Triples"); + const showAddRelation = useFeatureFlag("Reified Relation Triples"); if (!showAddRelation) return null; let extProps: ExtendedCreateRelationDialogProps | null = null; try { diff --git a/apps/roam/src/components/results-view/ResultsTable.tsx b/apps/roam/src/components/results-view/ResultsTable.tsx index c0f158b49..3ee89619d 100644 --- a/apps/roam/src/components/results-view/ResultsTable.tsx +++ b/apps/roam/src/components/results-view/ResultsTable.tsx @@ -24,7 +24,7 @@ import DiscourseContextOverlay from "~/components/DiscourseContextOverlay"; import { CONTEXT_OVERLAY_SUGGESTION } from "~/utils/predefinedSelections"; import { strictQueryForReifiedBlocks } from "~/utils/createReifiedBlock"; import internalError from "~/utils/internalError"; -import { getFeatureFlag } from "~/components/settings/utils/accessors"; +import { useFeatureFlag } from "~/components/settings/utils/hooks"; const EXTRA_ROW_TYPES = ["context", "discourse"] as const; type ExtraRowType = (typeof EXTRA_ROW_TYPES)[number] | null; @@ -262,7 +262,7 @@ const ResultRow = ({ onDragEnd, onRefresh, }: ResultRowProps) => { - const useReifiedRel = getFeatureFlag("Reified Relation Triples"); + const useReifiedRel = useFeatureFlag("Reified Relation Triples"); const cell = (key: string) => { const value = toCellValue({ value: r[`${key}-display`] || r[key] || "", diff --git a/apps/roam/src/components/settings/AdminPanel.tsx b/apps/roam/src/components/settings/AdminPanel.tsx index 9ab4bb2c0..b436bda9d 100644 --- a/apps/roam/src/components/settings/AdminPanel.tsx +++ b/apps/roam/src/components/settings/AdminPanel.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useMemo, useRef } from "react"; +import React, { useState, useEffect, useRef } from "react"; import { Button, Checkbox, @@ -31,7 +31,7 @@ import type { DGSupabaseClient } from "@repo/database/lib/client"; import internalError from "~/utils/internalError"; import SuggestiveModeSettings from "./SuggestiveModeSettings"; import { BlockPropFeatureFlagPanel } from "./components/BlockPropFeatureFlagPanel"; -import { getFeatureFlag } from "./utils/accessors"; +import { useFeatureFlag } from "./utils/hooks"; const NodeRow = ({ node }: { node: PConceptFull }) => { return ( @@ -256,7 +256,7 @@ const MigrationTab = (): React.ReactElement => { const [useMigrationResults, setMigrationResults] = useState(""); const [useOngoing, setOngoing] = useState(false); const [useDryRun, setDryRun] = useState(false); - const enabled = getFeatureFlag("Reified Relation Triples"); + const enabled = useFeatureFlag("Reified Relation Triples"); const doMigrateRelations = async () => { setOngoing(true); try { @@ -375,10 +375,9 @@ const FeatureFlagsTab = (): React.ReactElement => { window.location.reload()} + onConfirm={() => setIsInstructionOpen(false)} onCancel={() => setIsInstructionOpen(false)} - confirmButtonText="Reload Graph" - cancelButtonText="Later" + confirmButtonText="Got it" intent={Intent.PRIMARY} >

@@ -386,12 +385,8 @@ const FeatureFlagsTab = (): React.ReactElement => { upload all node embeddings to supabase.

- Please reload the graph to see the new 'Suggestive Mode' - tab. -

-

- Then go to Suggestive Mode{" "} - {"-> Sync Config -> Click on 'Generate & Upload All Node Embeddings'"} + Go to the new 'Suggestive Mode' tab, then Sync Config{" "} + {"-> Click on 'Generate & Upload All Node Embeddings'"}

@@ -422,10 +417,7 @@ const FeatureFlagsTab = (): React.ReactElement => { const AdminPanel = (): React.ReactElement => { const [selectedTabId, setSelectedTabId] = useState("admin"); - const suggestiveModeEnabled = useMemo( - () => getFeatureFlag("Suggestive Mode Enabled"), - [], - ); + const suggestiveModeEnabled = useFeatureFlag("Suggestive Mode Enabled"); return ( { @@ -12,8 +11,6 @@ const DiscourseGraphHome = () => { return getFormattedConfigTree(); }, []); - const [isAlertOpen, setIsAlertOpen] = useState(false); - return (
{ title="(BETA) Enable Left Sidebar" description="Whether or not to enable the left sidebar." featureKey="Enable Left Sidebar" - onAfterChange={(checked) => { - if (checked) { - setIsAlertOpen(true); - } - }} /> - window.location.reload()} - onCancel={() => setIsAlertOpen(false)} - confirmButtonText="Reload Graph" - cancelButtonText="Later" - intent={Intent.PRIMARY} - > -

Enabling the Left Sidebar requires a graph reload to take effect.

-

Would you like to reload now?

-
); }; diff --git a/apps/roam/src/components/settings/HomePersonalSettings.tsx b/apps/roam/src/components/settings/HomePersonalSettings.tsx index c48414850..304a37852 100644 --- a/apps/roam/src/components/settings/HomePersonalSettings.tsx +++ b/apps/roam/src/components/settings/HomePersonalSettings.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from "react"; +import React from "react"; import { OnloadArgs } from "roamjs-components/types"; import { Label, Checkbox } from "@blueprintjs/core"; import Description from "roamjs-components/components/Description"; @@ -27,12 +27,12 @@ import internalError from "~/utils/internalError"; import KeyboardShortcutInput from "./KeyboardShortcutInput"; import { getSetting, setSetting } from "~/utils/extensionSettings"; import streamlineStyling from "~/styles/streamlineStyling"; -import { getFeatureFlag } from "./utils/accessors"; +import { useFeatureFlag } from "./utils/hooks"; const HomePersonalSettings = ({ onloadArgs }: { onloadArgs: OnloadArgs }) => { const extensionAPI = onloadArgs.extensionAPI; const overlayHandler = getOverlayHandler(onloadArgs); - const suggestiveModeEnabled = useMemo(() => getFeatureFlag("Suggestive Mode Enabled"), []); + const suggestiveModeEnabled = useFeatureFlag("Suggestive Mode Enabled"); return (
diff --git a/apps/roam/src/components/settings/NodeConfig.tsx b/apps/roam/src/components/settings/NodeConfig.tsx index 54d801954..3fa3742a1 100644 --- a/apps/roam/src/components/settings/NodeConfig.tsx +++ b/apps/roam/src/components/settings/NodeConfig.tsx @@ -3,7 +3,6 @@ import React, { useCallback, useRef, useEffect, - useMemo, } from "react"; import { DiscourseNode } from "~/utils/getDiscourseNodes"; import FlagPanel from "roamjs-components/components/ConfigPanels/FlagPanel"; @@ -29,7 +28,7 @@ import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByPar import createBlock from "roamjs-components/writes/createBlock"; import updateBlock from "roamjs-components/writes/updateBlock"; import DiscourseNodeSuggestiveRules from "./DiscourseNodeSuggestiveRules"; -import { getFeatureFlag } from "./utils/accessors"; +import { useFeatureFlag } from "./utils/hooks"; import refreshConfigTree from "~/utils/refreshConfigTree"; export const getCleanTagText = (tag: string): string => { @@ -172,7 +171,7 @@ const NodeConfig = ({ node: DiscourseNode; onloadArgs: OnloadArgs; }) => { - const suggestiveModeEnabled = useMemo(() => getFeatureFlag("Suggestive Mode Enabled"), []); + const suggestiveModeEnabled = useFeatureFlag("Suggestive Mode Enabled"); const getUid = (key: string) => getSubTree({ parentUid: node.type, diff --git a/apps/roam/src/components/settings/utils/hooks.ts b/apps/roam/src/components/settings/utils/hooks.ts new file mode 100644 index 000000000..caba47be5 --- /dev/null +++ b/apps/roam/src/components/settings/utils/hooks.ts @@ -0,0 +1,41 @@ +import { useState, useEffect } from "react"; +import { getFeatureFlag } from "./accessors"; +import type { FeatureFlags } from "./zodSchema"; + +const FEATURE_FLAG_CHANGE_EVENT = "discourse-graph:feature-flag-change"; + +type FeatureFlagChangeDetail = { + key: keyof FeatureFlags; + value: boolean; +}; + +export const emitFeatureFlagChange = ( + key: keyof FeatureFlags, + value: boolean, +): void => { + window.dispatchEvent( + new CustomEvent(FEATURE_FLAG_CHANGE_EVENT, { + detail: { key, value }, + }), + ); +}; + +export const useFeatureFlag = (key: keyof FeatureFlags): boolean => { + const [value, setValue] = useState(() => getFeatureFlag(key)); + + useEffect(() => { + const handleChange = (event: Event) => { + const customEvent = event as CustomEvent; + if (customEvent.detail.key === key) { + setValue(customEvent.detail.value); + } + }; + + window.addEventListener(FEATURE_FLAG_CHANGE_EVENT, handleChange); + return () => { + window.removeEventListener(FEATURE_FLAG_CHANGE_EVENT, handleChange); + }; + }, [key]); + + return value; +}; diff --git a/apps/roam/src/components/settings/utils/pullWatchers.ts b/apps/roam/src/components/settings/utils/pullWatchers.ts index 51659846c..137ad1161 100644 --- a/apps/roam/src/components/settings/utils/pullWatchers.ts +++ b/apps/roam/src/components/settings/utils/pullWatchers.ts @@ -12,11 +12,15 @@ import { type PersonalSettings, type DiscourseNodeSettings, } from "./zodSchema"; -import { render as renderToast } from "roamjs-components/components/Toast"; import { unmountLeftSidebar, remountLeftSidebar, } from "~/components/LeftSidebarView"; +import { + initializeSupabaseSync, + setSyncActivity, +} from "~/utils/syncDgNodesToSupabase"; +import { emitFeatureFlagChange } from "./hooks"; type PullWatchCallback = Parameters[2]; @@ -94,6 +98,7 @@ export const featureFlagHandlers: Partial< > = { "Enable Left Sidebar": (newValue, oldValue) => { if (newValue !== oldValue) { + emitFeatureFlagChange("Enable Left Sidebar", newValue); if (newValue) { void remountLeftSidebar(); } else { @@ -103,22 +108,17 @@ export const featureFlagHandlers: Partial< }, "Suggestive Mode Enabled": (newValue, oldValue) => { if (newValue !== oldValue) { - renderToast({ - id: "suggestive-mode-changed", - content: `Suggestive Mode ${newValue ? "enabled" : "disabled"}. Please reload the graph for changes to take effect.`, - intent: "primary", - timeout: 5000, - }); + emitFeatureFlagChange("Suggestive Mode Enabled", newValue); + if (newValue) { + initializeSupabaseSync(); + } else { + setSyncActivity(false); + } } }, "Reified Relation Triples": (newValue, oldValue) => { if (newValue !== oldValue) { - renderToast({ - id: "reified-relations-changed", - content: `Reified Relation Triples ${newValue ? "enabled" : "disabled"}. Please reload the graph for changes to take effect.`, - intent: "primary", - timeout: 5000, - }); + emitFeatureFlagChange("Reified Relation Triples", newValue); } }, }; diff --git a/apps/roam/src/index.ts b/apps/roam/src/index.ts index 2aebb8916..1026b20e2 100644 --- a/apps/roam/src/index.ts +++ b/apps/roam/src/index.ts @@ -31,17 +31,13 @@ import { setSyncActivity, } from "./utils/syncDgNodesToSupabase"; import { initPluginTimer } from "./utils/pluginTimer"; -import { getUidAndBooleanSetting } from "./utils/getExportSettings"; -import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByParentUid"; -import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTitle"; -import { DISCOURSE_CONFIG_PAGE_TITLE } from "./utils/renderNodeConfigPage"; import { getSetting } from "./utils/extensionSettings"; import { initPostHog } from "./utils/posthog"; import { STREAMLINE_STYLING_KEY, DISALLOW_DIAGNOSTICS, } from "./data/userSettings"; - +import { getFeatureFlag } from "./components/settings/utils/accessors"; export const DEFAULT_CANVAS_PAGE_FORMAT = "Canvas/*"; @@ -114,14 +110,9 @@ export default runExtension(async (onloadArgs) => { document.addEventListener("input", discourseNodeSearchTriggerListener); document.addEventListener("selectionchange", nodeCreationPopoverListener); - const isSuggestiveModeEnabled = getUidAndBooleanSetting({ - tree: getBasicTreeByParentUid( - getPageUidByPageTitle(DISCOURSE_CONFIG_PAGE_TITLE), - ), - text: "(BETA) Suggestive Mode Enabled", - }).value; - - if (isSuggestiveModeEnabled) { + // Initialize sync if suggestive mode was already enabled before plugin load + // (pull watcher handles reactive changes after this) + if (getFeatureFlag("Suggestive Mode Enabled")) { initializeSupabaseSync(); } diff --git a/apps/roam/src/utils/discourseConfigRef.ts b/apps/roam/src/utils/discourseConfigRef.ts index 24f758269..bb9f101bc 100644 --- a/apps/roam/src/utils/discourseConfigRef.ts +++ b/apps/roam/src/utils/discourseConfigRef.ts @@ -4,8 +4,6 @@ import { StringSetting, ExportConfigWithUids, getUidAndStringSetting, - getUidAndBooleanSetting, - BooleanSetting, } from "./getExportSettings"; import { DISCOURSE_CONFIG_PAGE_TITLE } from "~/utils/renderNodeConfigPage"; import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTitle"; @@ -44,8 +42,6 @@ type FormattedConfigTree = { canvasPageFormat: StringSetting; suggestiveMode: SuggestiveModeConfigWithUids; leftSidebar: LeftSidebarConfig; - leftSidebarEnabled: BooleanSetting; - suggestiveModeEnabled: BooleanSetting; }; export const getFormattedConfigTree = (): FormattedConfigTree => { @@ -74,14 +70,6 @@ export const getFormattedConfigTree = (): FormattedConfigTree => { }), suggestiveMode: getSuggestiveModeConfigAndUids(configTreeRef.tree), leftSidebar: getLeftSidebarSettings(configTreeRef.tree), - leftSidebarEnabled: getUidAndBooleanSetting({ - tree: configTreeRef.tree, - text: "(BETA) Left Sidebar", - }), - suggestiveModeEnabled: getUidAndBooleanSetting({ - tree: configTreeRef.tree, - text: "(BETA) Suggestive Mode Enabled", - }), }; }; export default configTreeRef; From 1adcb4ee630355991d7167041e0fa30dc189d02d Mon Sep 17 00:00:00 2001 From: sid597 Date: Mon, 12 Jan 2026 21:06:13 +0530 Subject: [PATCH 6/6] fix --- .../src/components/LeftSidebar/lifecycle.ts | 29 +++++++++++ apps/roam/src/components/LeftSidebarView.tsx | 9 ++++ .../src/components/settings/AdminPanel.tsx | 6 +-- .../components/settings/GeneralSettings.tsx | 4 +- .../components/BlockPropFeatureFlagPanel.tsx | 48 ------------------- .../components/settings/utils/pullWatchers.ts | 42 ++++++++-------- 6 files changed, 63 insertions(+), 75 deletions(-) create mode 100644 apps/roam/src/components/LeftSidebar/lifecycle.ts delete mode 100644 apps/roam/src/components/settings/components/BlockPropFeatureFlagPanel.tsx diff --git a/apps/roam/src/components/LeftSidebar/lifecycle.ts b/apps/roam/src/components/LeftSidebar/lifecycle.ts new file mode 100644 index 000000000..94082f008 --- /dev/null +++ b/apps/roam/src/components/LeftSidebar/lifecycle.ts @@ -0,0 +1,29 @@ +type LeftSidebarLifecycle = { + mount: (() => Promise) | null; + unmount: (() => void) | null; +}; + +const lifecycle: LeftSidebarLifecycle = { + mount: null, + unmount: null, +}; + +export const registerLeftSidebarLifecycle = (fns: { + mount: () => Promise; + unmount: () => void; +}): void => { + lifecycle.mount = fns.mount; + lifecycle.unmount = fns.unmount; +}; + +export const remountLeftSidebar = async (): Promise => { + if (lifecycle.mount) { + await lifecycle.mount(); + } +}; + +export const unmountLeftSidebar = (): void => { + if (lifecycle.unmount) { + lifecycle.unmount(); + } +}; diff --git a/apps/roam/src/components/LeftSidebarView.tsx b/apps/roam/src/components/LeftSidebarView.tsx index 5635c1d00..fc27171d6 100644 --- a/apps/roam/src/components/LeftSidebarView.tsx +++ b/apps/roam/src/components/LeftSidebarView.tsx @@ -42,6 +42,7 @@ import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByPar import { DISCOURSE_CONFIG_PAGE_TITLE } from "~/utils/renderNodeConfigPage"; import getPageTitleByPageUid from "roamjs-components/queries/getPageTitleByPageUid"; import { migrateLeftSidebarSettings } from "~/utils/migrateLeftSidebarSettings"; +import { registerLeftSidebarLifecycle } from "./LeftSidebar/lifecycle"; const parseReference = (text: string) => { const extracted = extractRef(text); @@ -508,6 +509,9 @@ const migrateFavorites = async () => { refreshConfigTree(); }; +// TODO: Temporary cache for onloadArgs - will be removed when left sidebar is fully migrated +// to block prop settings. Currently needed because remountLeftSidebar() is called from +// pullWatchers.ts which doesn't have access to onloadArgs. let cachedOnloadArgs: OnloadArgs | null = null; export const cacheOnloadArgs = (onloadArgs: OnloadArgs): void => { @@ -559,4 +563,9 @@ export const remountLeftSidebar = async (): Promise => { await mountLeftSidebar(wrapper, cachedOnloadArgs); }; +registerLeftSidebarLifecycle({ + mount: remountLeftSidebar, + unmount: unmountLeftSidebar, +}); + export default LeftSidebarView; diff --git a/apps/roam/src/components/settings/AdminPanel.tsx b/apps/roam/src/components/settings/AdminPanel.tsx index b436bda9d..138e6569c 100644 --- a/apps/roam/src/components/settings/AdminPanel.tsx +++ b/apps/roam/src/components/settings/AdminPanel.tsx @@ -30,7 +30,7 @@ import { countReifiedRelations } from "~/utils/createReifiedBlock"; import type { DGSupabaseClient } from "@repo/database/lib/client"; import internalError from "~/utils/internalError"; import SuggestiveModeSettings from "./SuggestiveModeSettings"; -import { BlockPropFeatureFlagPanel } from "./components/BlockPropFeatureFlagPanel"; +import { FeatureFlagPanel } from "./components/BlockPropSettingPanels"; import { useFeatureFlag } from "./utils/hooks"; const NodeRow = ({ node }: { node: PConceptFull }) => { @@ -339,7 +339,7 @@ const FeatureFlagsTab = (): React.ReactElement => { return (
- {

- { const settings = useMemo(() => { @@ -30,7 +30,7 @@ const DiscourseGraphHome = () => { value={settings.canvasPageFormat.value} defaultValue={DEFAULT_CANVAS_PAGE_FORMAT} /> - Promise; - onAfterChange?: (checked: boolean) => void; -}) => { - const [value, setValue] = useState(() => getFeatureFlag(featureKey)); - - const handleChange = async (e: React.ChangeEvent) => { - const { checked } = e.target; - - if (checked && onBeforeEnable) { - const shouldProceed = await onBeforeEnable(); - if (!shouldProceed) return; - } - - setFeatureFlag(featureKey, checked); - setValue(checked); - onAfterChange?.(checked); - }; - - return ( - void handleChange(e)} - labelElement={ - <> - {idToTitle(title)} - - - } - /> - ); -}; diff --git a/apps/roam/src/components/settings/utils/pullWatchers.ts b/apps/roam/src/components/settings/utils/pullWatchers.ts index 137ad1161..7c4453a2b 100644 --- a/apps/roam/src/components/settings/utils/pullWatchers.ts +++ b/apps/roam/src/components/settings/utils/pullWatchers.ts @@ -13,9 +13,9 @@ import { type DiscourseNodeSettings, } from "./zodSchema"; import { - unmountLeftSidebar, remountLeftSidebar, -} from "~/components/LeftSidebarView"; + unmountLeftSidebar, +} from "~/components/LeftSidebar/lifecycle"; import { initializeSupabaseSync, setSyncActivity, @@ -96,30 +96,28 @@ const addPullWatch = ( export const featureFlagHandlers: Partial< Record void> > = { - "Enable Left Sidebar": (newValue, oldValue) => { - if (newValue !== oldValue) { - emitFeatureFlagChange("Enable Left Sidebar", newValue); - if (newValue) { - void remountLeftSidebar(); - } else { - unmountLeftSidebar(); - } + // eslint-disable-next-line @typescript-eslint/naming-convention + "Enable Left Sidebar": (newValue) => { + emitFeatureFlagChange("Enable Left Sidebar", newValue); + if (newValue) { + void remountLeftSidebar(); + } else { + unmountLeftSidebar(); } }, - "Suggestive Mode Enabled": (newValue, oldValue) => { - if (newValue !== oldValue) { - emitFeatureFlagChange("Suggestive Mode Enabled", newValue); - if (newValue) { - initializeSupabaseSync(); - } else { - setSyncActivity(false); - } + // eslint-disable-next-line @typescript-eslint/naming-convention + "Suggestive Mode Enabled": (newValue) => { + emitFeatureFlagChange("Suggestive Mode Enabled", newValue); + if (newValue) { + initializeSupabaseSync(); + } else { + setSyncActivity(false); } }, - "Reified Relation Triples": (newValue, oldValue) => { - if (newValue !== oldValue) { - emitFeatureFlagChange("Reified Relation Triples", newValue); - } + + // eslint-disable-next-line @typescript-eslint/naming-convention + "Reified Relation Triples": (newValue) => { + emitFeatureFlagChange("Reified Relation Triples", newValue); }, };