diff --git a/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx b/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx index aa11d6161..66aa09721 100644 --- a/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx @@ -67,17 +67,28 @@ const toRecord = (attrs: Attribute[]): Record => const NodeAttributes = ({ uid, nodeType, + defaultValue, }: { uid: string; nodeType: string; + defaultValue?: Record; }) => { - const [attributes, setAttributes] = useState(() => - getBasicTreeByParentUid(uid).map((t) => ({ + const [attributes, setAttributes] = useState(() => { + const tree = getBasicTreeByParentUid(uid); + if (defaultValue && Object.keys(defaultValue).length > 0) { + const treeByLabel = new Map(tree.map((t) => [t.text, t])); + return Object.entries(defaultValue).map(([label, value]) => ({ + uid: treeByLabel.get(label)?.uid ?? "", + label, + value, + })); + } + return tree.map((t) => ({ uid: t.uid, label: t.text, value: t.children[0]?.text, - })), - ); + })); + }); const attributesRef = useRef(attributes); attributesRef.current = attributes; const syncToBlockProps = () => { @@ -93,7 +104,7 @@ const NodeAttributes = ({
{attributes.map((a) => ( setAttributes( diff --git a/apps/roam/src/components/settings/DiscourseNodeSuggestiveRules.tsx b/apps/roam/src/components/settings/DiscourseNodeSuggestiveRules.tsx index 3f31cec06..6fc756ff1 100644 --- a/apps/roam/src/components/settings/DiscourseNodeSuggestiveRules.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeSuggestiveRules.tsx @@ -75,6 +75,7 @@ const DiscourseNodeSuggestiveRules = ({ description={`The template that auto fills ${node.text} page when generated.`} settingKeys={TEMPLATE_SETTING_KEYS} uid={templateUid} + defaultValue={node.template} />
} @@ -343,6 +344,10 @@ const NodeConfig = ({ >( + node.type, + [DISCOURSE_NODE_KEYS.attributes], + )} /> @@ -33,9 +34,12 @@ const DualWriteBlocksPanel = ({ title, description, uid, + defaultValue, }: DualWriteBlocksPanelProps) => { const containerRef = useRef(null); const debounceRef = useRef(0); + const defaultValueRef = useRef(defaultValue); + defaultValueRef.current = defaultValue; const pullWatchArgsRef = useRef< [string, string, (before: unknown, after: unknown) => void] | null >(null); @@ -62,17 +66,23 @@ const DualWriteBlocksPanel = ({ window.roamAlphaAPI.data.addPullWatch(pattern, entityId, callback); }; - if (!getFirstChildUidByBlockUid(uid)) { - void createBlock({ node: { text: " " }, parentUid: uid }).then(() => { - el.innerHTML = ""; - void window.roamAlphaAPI.ui.components.renderBlock({ uid, el }); - registerPullWatch(); - }); - } else { + const dv = defaultValueRef.current; + const ensureChildren = getFirstChildUidByBlockUid(uid) + ? Promise.resolve() + : (dv && dv.length > 0 + ? Promise.all( + dv.map((node, i) => + createBlock({ node, parentUid: uid, order: i }), + ), + ) + : createBlock({ node: { text: " " }, parentUid: uid }) + ).then(() => {}); + + void ensureChildren.then(() => { el.innerHTML = ""; void window.roamAlphaAPI.ui.components.renderBlock({ uid, el }); registerPullWatch(); - } + }); return () => { window.clearTimeout(debounceRef.current); diff --git a/apps/roam/src/index.ts b/apps/roam/src/index.ts index d8ae5ff3e..10ad6db4c 100644 --- a/apps/roam/src/index.ts +++ b/apps/roam/src/index.ts @@ -36,6 +36,7 @@ import { initPostHog } from "./utils/posthog"; import { initSchema } from "./components/settings/utils/init"; import { bulkReadSettings, + isNewSettingsStoreEnabled, isSyncEnabled, } from "./components/settings/utils/accessors"; import { PERSONAL_KEYS } from "./components/settings/utils/settingKeys"; @@ -128,6 +129,45 @@ export default runExtension(async (onloadArgs) => { } const { extensionAPI } = onloadArgs; + if (isNewSettingsStoreEnabled()) { + const personalLegacyKeys = [ + "discourse-context-overlay", + "text-selection-popup", + "disable-sidebar-open", + "page-preview", + "hide-feedback-button", + "auto-canvas-relations", + "discourse-context-overlay-in-canvas", + "streamline-styling", + "disallow-diagnostics", + "discourse-tool-shortcut", + "personal-node-menu-trigger", + "node-search-trigger", + "hide-metadata", + "default-page-size", + "query-pages", + "default-filters", + "use-reified-relations", + "canvas-page-format", + ]; + void extensionAPI.ui.commandPalette.addCommand({ + label: "DG: Dev - Nuke personal legacy settings", + callback: () => { + const before = Object.fromEntries( + personalLegacyKeys.map((k) => [k, extensionAPI.settings.get(k)]), + ); + console.log("[dg] personal legacy BEFORE nuke:", before); + void Promise.all( + personalLegacyKeys.map((k) => extensionAPI.settings.set(k, null)), + ).then(() => { + const after = Object.fromEntries( + personalLegacyKeys.map((k) => [k, extensionAPI.settings.get(k)]), + ); + console.log("[dg] personal legacy AFTER nuke:", after); + }); + }, + }); + } window.roamjs.extension.queryBuilder = { runQuery: (parentUid: string) => runQuery({ parentUid, extensionAPI }).then( diff --git a/apps/roam/src/utils/getExportSettings.ts b/apps/roam/src/utils/getExportSettings.ts index c0d4dc9f6..0c53fe238 100644 --- a/apps/roam/src/utils/getExportSettings.ts +++ b/apps/roam/src/utils/getExportSettings.ts @@ -3,6 +3,8 @@ import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTit import { RoamBasicNode } from "roamjs-components/types"; import { getSubTree } from "roamjs-components/util"; import { DISCOURSE_CONFIG_PAGE_TITLE } from "~/data/constants"; +import { bulkReadSettings } from "~/components/settings/utils/accessors"; +import { EXPORT_KEYS } from "~/components/settings/utils/settingKeys"; type UidPair = { uid?: string; @@ -110,16 +112,17 @@ export const getExportSettingsAndUids = (): ExportConfigWithUids => { }; export const getExportSettings = (): Omit => { - const settings = getExportSettingsAndUids(); + const exportValues = bulkReadSettings().globalSettings.Export; + const legacy = getExportSettingsAndUids(); return { - maxFilenameLength: settings.maxFilenameLength.value, - openSidebar: settings.openSidebar.value, - removeSpecialCharacters: settings.removeSpecialCharacters.value, - simplifiedFilename: settings.simplifiedFilename.value, - optsEmbeds: settings.optsEmbeds.value, - optsRefs: settings.optsRefs.value, - linkType: settings.linkType.value, - appendRefNodeContext: settings.appendRefNodeContext.value, - frontmatter: settings.frontmatter.values, + maxFilenameLength: exportValues[EXPORT_KEYS.maxFilenameLength], + removeSpecialCharacters: exportValues[EXPORT_KEYS.removeSpecialCharacters], + optsEmbeds: exportValues[EXPORT_KEYS.resolveBlockEmbeds], + optsRefs: exportValues[EXPORT_KEYS.resolveBlockReferences], + linkType: exportValues[EXPORT_KEYS.linkType], + appendRefNodeContext: exportValues[EXPORT_KEYS.appendReferencedNode], + frontmatter: exportValues[EXPORT_KEYS.frontmatter], + openSidebar: legacy.openSidebar.value, + simplifiedFilename: legacy.simplifiedFilename.value, }; }; diff --git a/apps/roam/src/utils/getLeftSidebarSettings.ts b/apps/roam/src/utils/getLeftSidebarSettings.ts index 928f6a067..3d5203c99 100644 --- a/apps/roam/src/utils/getLeftSidebarSettings.ts +++ b/apps/roam/src/utils/getLeftSidebarSettings.ts @@ -204,30 +204,42 @@ export const getAllLeftSidebarPersonalSectionConfigs = ( return result; }; -// TODO(ENG-1471): Remove when migration complete — just use accessor values directly. -// During dual-read, we need old-system UIDs for block CRUD (fold toggle, reorder, delete) -// but read setting VALUES from accessors (which route through the feature flag and log -// mismatches). These helpers merge accessor values onto old-system config objects. export const mergeGlobalSectionWithAccessor = ( config: LeftSidebarGlobalSectionConfig, globalValues: LeftSidebarGlobalSettings | undefined, ): LeftSidebarGlobalSectionConfig => { - if (!config.settings) return config; - return { - ...config, - settings: { - uid: config.settings.uid, - collapsable: { - uid: config.settings.collapsable.uid, - value: - globalValues?.Settings.Collapsable ?? - config.settings.collapsable.value, - }, - folded: { - uid: config.settings.folded.uid, - value: globalValues?.Settings.Folded ?? config.settings.folded.value, - }, + const legacyChildByPageUid = new Map(config.children.map((c) => [c.text, c])); + const children: RoamBasicNode[] = (globalValues?.Children ?? []).map( + (targetPageUid) => { + const legacyChild = legacyChildByPageUid.get(targetPageUid); + return { + uid: legacyChild?.uid ?? "", + text: targetPageUid, + children: legacyChild?.children ?? [], + }; }, + ); + + return { + uid: config.uid, + childrenUid: config.childrenUid, + children, + settings: config.settings + ? { + uid: config.settings.uid, + collapsable: { + uid: config.settings.collapsable.uid, + value: + globalValues?.Settings.Collapsable ?? + config.settings.collapsable.value, + }, + folded: { + uid: config.settings.folded.uid, + value: + globalValues?.Settings.Folded ?? config.settings.folded.value, + }, + } + : undefined, }; }; @@ -235,22 +247,44 @@ export const mergePersonalSectionsWithAccessor = ( sections: LeftSidebarPersonalSectionConfig[], personalValues: PersonalSection[] | undefined, ): LeftSidebarPersonalSectionConfig[] => { - return sections.map((section, i) => { - const newSection = personalValues?.[i]; - if (!section.settings || !newSection) return section; + const legacyByName = new Map(sections.map((s) => [s.text, s])); + return (personalValues ?? []).map((snap) => { + const legacy = legacyByName.get(snap.name); + const legacyChildByPageUid = new Map( + (legacy?.children ?? []).map((c) => [c.text, c]), + ); return { - ...section, - settings: { - ...section.settings, - truncateResult: { - ...section.settings.truncateResult, - value: newSection.Settings["Truncate-result?"], - }, - folded: { - ...section.settings.folded, - value: newSection.Settings.Folded, - }, - }, + uid: legacy?.uid ?? "", + text: snap.name, + settings: legacy?.settings + ? { + uid: legacy.settings.uid, + truncateResult: { + uid: legacy.settings.truncateResult.uid, + value: snap.Settings["Truncate-result?"], + }, + folded: { + uid: legacy.settings.folded.uid, + value: snap.Settings.Folded, + }, + } + : undefined, + children: + snap.Children.length > 0 + ? snap.Children.map((snapChild) => { + const legacyChild = legacyChildByPageUid.get(snapChild.uid); + return { + uid: legacyChild?.uid ?? "", + text: snapChild.uid, + children: legacyChild?.children ?? [], + alias: { + uid: legacyChild?.alias.uid, + value: snapChild.Alias, + }, + }; + }) + : [], + childrenUid: legacy?.childrenUid, }; }); };