Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions apps/roam/src/components/settings/DiscourseNodeAttributes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,28 @@ const toRecord = (attrs: Attribute[]): Record<string, string> =>
const NodeAttributes = ({
uid,
nodeType,
defaultValue,
}: {
uid: string;
nodeType: string;
defaultValue?: Record<string, string>;
}) => {
const [attributes, setAttributes] = useState<Attribute[]>(() =>
getBasicTreeByParentUid(uid).map((t) => ({
const [attributes, setAttributes] = useState<Attribute[]>(() => {
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,
}));
Comment thread
sid597 marked this conversation as resolved.
}
return tree.map((t) => ({
uid: t.uid,
label: t.text,
value: t.children[0]?.text,
})),
);
}));
});
const attributesRef = useRef(attributes);
attributesRef.current = attributes;
const syncToBlockProps = () => {
Expand All @@ -93,7 +104,7 @@ const NodeAttributes = ({
<div style={{ marginBottom: 32 }}>
{attributes.map((a) => (
<NodeAttribute
key={a.uid}
key={a.label}
{...a}
onChange={(v) =>
setAttributes(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}
/>

<DiscourseNodeTextPanel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ const LeftSidebarGlobalSectionsContent = ({
} else {
const merged = mergeGlobalSectionWithAccessor(config, globalValues);
setChildrenUid(merged.childrenUid || null);
setPages(merged.children || []);
setPages(merged.children);
setGlobalSection(merged);
}
setIsInitializing(false);
Expand Down
5 changes: 5 additions & 0 deletions apps/roam/src/components/settings/NodeConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ const NodeConfig = ({
description={`The template that auto fills ${node.text} page when generated.`}
settingKeys={TEMPLATE_SETTING_KEYS}
uid={templateUid}
defaultValue={node.template}
/>
</div>
}
Expand All @@ -343,6 +344,10 @@ const NodeConfig = ({
<DiscourseNodeAttributes
uid={attributeNode.uid}
nodeType={node.type}
defaultValue={getDiscourseNodeSetting<Record<string, string>>(
node.type,
[DISCOURSE_NODE_KEYS.attributes],
)}
/>
<DiscourseNodeSelectPanel
nodeType={node.type}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Description from "roamjs-components/components/Description";
import createBlock from "roamjs-components/writes/createBlock";
import getFullTreeByParentUid from "roamjs-components/queries/getFullTreeByParentUid";
import getFirstChildUidByBlockUid from "roamjs-components/queries/getFirstChildUidByBlockUid";
import type { TreeNode } from "roamjs-components/types";
import type { InputTextNode, TreeNode } from "roamjs-components/types";
import type { RoamNodeType } from "~/components/settings/utils/zodSchema";
import { setDiscourseNodeSetting } from "~/components/settings/utils/accessors";
import type { DiscourseNodeBaseProps } from "./BlockPropSettingPanels";
Expand All @@ -13,6 +13,7 @@ const DEBOUNCE_MS = 250;

type DualWriteBlocksPanelProps = DiscourseNodeBaseProps & {
uid: string;
defaultValue?: InputTextNode[];
};

const serializeBlockTree = (children: TreeNode[]): RoamNodeType[] =>
Expand All @@ -33,9 +34,12 @@ const DualWriteBlocksPanel = ({
title,
description,
uid,
defaultValue,
}: DualWriteBlocksPanelProps) => {
const containerRef = useRef<HTMLDivElement>(null);
const debounceRef = useRef(0);
const defaultValueRef = useRef(defaultValue);
defaultValueRef.current = defaultValue;
const pullWatchArgsRef = useRef<
[string, string, (before: unknown, after: unknown) => void] | null
>(null);
Expand All @@ -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);
Expand Down
40 changes: 40 additions & 0 deletions apps/roam/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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(
Expand Down
23 changes: 13 additions & 10 deletions apps/roam/src/utils/getExportSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> = {
uid?: string;
Expand Down Expand Up @@ -110,16 +112,17 @@ export const getExportSettingsAndUids = (): ExportConfigWithUids => {
};

export const getExportSettings = (): Omit<ExportConfig, "exportUid"> => {
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,
};
};
102 changes: 68 additions & 34 deletions apps/roam/src/utils/getLeftSidebarSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,53 +204,87 @@ 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,
};
};

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,
};
});
};
Expand Down
Loading