Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
50 changes: 29 additions & 21 deletions apps/roam/src/components/LeftSidebarView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { getLeftSidebarSettings } from "~/utils/getLeftSidebarSettings";
import {
getGlobalSetting,
getPersonalSetting,
getPersonalSettings,
setGlobalSetting,
setPersonalSetting,
} from "~/components/settings/utils/accessors";
Expand All @@ -45,10 +46,7 @@ import {
LEFT_SIDEBAR_KEYS,
LEFT_SIDEBAR_SETTINGS_KEYS,
} from "~/components/settings/utils/settingKeys";
import type {
LeftSidebarGlobalSettings,
PersonalSection,
} from "~/components/settings/utils/zodSchema";
import type { LeftSidebarGlobalSettings } from "~/components/settings/utils/zodSchema";
import { createBlock } from "roamjs-components/writes";
import deleteBlock from "roamjs-components/writes/deleteBlock";
import getTextByBlockUid from "roamjs-components/queries/getTextByBlockUid";
Expand Down Expand Up @@ -112,7 +110,7 @@ const openTarget = async (e: React.MouseEvent, targetUid: string) => {
}
};

const toggleFoldedState = ({
const toggleFoldedState = async ({
isOpen,
setIsOpen,
folded,
Expand All @@ -130,23 +128,26 @@ const toggleFoldedState = ({
const newFolded = !isOpen;

if (isOpen) {
setIsOpen(false);
if (folded.uid) {
void deleteBlock(folded.uid);
folded.uid = undefined;
folded.value = false;
}
const children = getBasicTreeByParentUid(parentUid);
await Promise.all(
children
.filter((c) => c.text === "Folded")
.map((c) => deleteBlock(c.uid)),
);
folded.uid = undefined;
folded.value = false;
} else {
setIsOpen(true);
const newUid = window.roamAlphaAPI.util.generateUID();
void createBlock({
await createBlock({
parentUid,
node: { text: "Folded", uid: newUid },
});
folded.uid = newUid;
folded.value = true;
}

refreshConfigTree();

if (isGlobal) {
setGlobalSetting(
[
Expand All @@ -157,13 +158,20 @@ const toggleFoldedState = ({
newFolded,
);
} else if (sectionIndex !== undefined) {
const sections =
getPersonalSetting<PersonalSection[]>([PERSONAL_KEYS.leftSidebar]) || [];
const sections = [...getPersonalSettings()[PERSONAL_KEYS.leftSidebar]];
if (sections[sectionIndex]) {
sections[sectionIndex].Settings.Folded = newFolded;
sections[sectionIndex] = {
...sections[sectionIndex],
Settings: {
...sections[sectionIndex].Settings,
Folded: newFolded,
},
};
setPersonalSetting([PERSONAL_KEYS.leftSidebar], sections);
}
}

setIsOpen(newFolded);
Comment thread
sid597 marked this conversation as resolved.
};

const SectionChildren = ({
Expand Down Expand Up @@ -225,7 +233,7 @@ const PersonalSectionItem = ({
const handleChevronClick = () => {
if (!section.settings) return;

toggleFoldedState({
void toggleFoldedState({
isOpen,
setIsOpen,
folded: section.settings.folded,
Expand Down Expand Up @@ -297,7 +305,7 @@ const GlobalSection = ({ config }: { config: LeftSidebarConfig["global"] }) => {
className="sidebar-title-button flex w-full items-center border-none bg-transparent py-1 pl-6 pr-2.5 font-semibold outline-none"
onClick={() => {
if (!isCollapsable || !config.settings) return;
toggleFoldedState({
void toggleFoldedState({
isOpen,
setIsOpen,
folded: config.settings.folded,
Expand Down Expand Up @@ -333,9 +341,9 @@ const buildConfig = (): LeftSidebarConfig => {
const globalValues = getGlobalSetting<LeftSidebarGlobalSettings>([
GLOBAL_KEYS.leftSidebar,
]);
const personalValues = getPersonalSetting<PersonalSection[]>([
PERSONAL_KEYS.leftSidebar,
]);
const personalValues = getPersonalSetting<
ReturnType<typeof getPersonalSettings>[typeof PERSONAL_KEYS.leftSidebar]
>([PERSONAL_KEYS.leftSidebar]);

// Read UIDs from old system (needed for fold CRUD during dual-write)
const oldConfig = getCurrentLeftSidebarConfig();
Expand Down
18 changes: 11 additions & 7 deletions apps/roam/src/components/settings/AdminPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ const FeatureFlagsTab = (): React.ReactElement => {
}, []);

const [suggestiveModeEnabled, setSuggestiveModeEnabled] = useState(
getFeatureFlag("Suggestive mode enabled"),
() => getFeatureFlag("Suggestive mode enabled"),
);
const [suggestiveModeUid, setSuggestiveModeUid] = useState(
legacySuggestiveModeMeta.suggestiveModeEnabledUid,
Expand All @@ -294,12 +294,15 @@ const FeatureFlagsTab = (): React.ReactElement => {
if (checked) {
setIsAlertOpen(true);
} else {
if (suggestiveModeUid) {
void deleteBlock(suggestiveModeUid);
setSuggestiveModeUid(undefined);
}
setSuggestiveModeEnabled(false);
setFeatureFlag("Suggestive mode enabled", false);
void (async () => {
if (suggestiveModeUid) {
await deleteBlock(suggestiveModeUid);
setSuggestiveModeUid(undefined);
}
refreshConfigTree();
setSuggestiveModeEnabled(false);
setFeatureFlag("Suggestive mode enabled", false);
})();
}
}}
labelElement={
Expand All @@ -321,6 +324,7 @@ const FeatureFlagsTab = (): React.ReactElement => {
node: { text: "(BETA) Suggestive Mode Enabled" },
}).then((uid) => {
setSuggestiveModeUid(uid);
refreshConfigTree();
setSuggestiveModeEnabled(true);
setFeatureFlag("Suggestive mode enabled", true);
setIsAlertOpen(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,9 @@ const SectionItem = memo(
order: 0,
node: { text: "Settings" },
});
const foldedUid = await createBlock({
parentUid: settingsUid,
order: 0,
node: { text: "Folded" },
});
const truncateSettingUid = await createBlock({
parentUid: settingsUid,
order: 1,
order: 0,
node: { text: "Truncate-result?", children: [{ text: "75" }] },
});

Expand All @@ -149,7 +144,7 @@ const SectionItem = memo(
...s,
settings: {
uid: settingsUid,
folded: { uid: foldedUid, value: false },
folded: { uid: undefined, value: false },
truncateResult: { uid: truncateSettingUid, value: 75 },
},
childrenUid,
Expand All @@ -167,7 +162,7 @@ const SectionItem = memo(
...s,
settings: {
uid: settingsUid,
folded: { uid: foldedUid, value: false },
folded: { uid: undefined, value: false },
truncateResult: { uid: truncateSettingUid, value: 75 },
},
children: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import Description from "roamjs-components/components/Description";
import useSingleChildValue from "roamjs-components/components/ConfigPanels/useSingleChildValue";
import getShallowTreeByParentUid from "roamjs-components/queries/getShallowTreeByParentUid";
import refreshConfigTree from "~/utils/refreshConfigTree";
import {
getGlobalSetting,
getPersonalSetting,
Expand Down Expand Up @@ -143,8 +144,9 @@ const BaseTextPanel = ({
window.clearTimeout(debounceRef.current);
debounceRef.current = window.setTimeout(() => {
if (errorRef.current) return;
setter(settingKeys, newValue);
syncToBlock?.(newValue);
refreshConfigTree();
setter(settingKeys, newValue);
Comment thread
sid597 marked this conversation as resolved.
Outdated
}, DEBOUNCE_MS);
};

Expand Down Expand Up @@ -227,9 +229,13 @@ const BaseFlagPanel = ({
}

setInternalValue(checked);
setter(settingKeys, checked);
await syncFlagToBlock(checked);
onChange?.(checked);
refreshConfigTree();
setter(settingKeys, checked);
// Delay onChange to let the async Roam block.update flush before
// the re-render reads block props via dual-read comparison.
// TODO(ENG-1471): remove with dual-read cleanup
setTimeout(() => onChange?.(checked), 100);
};

return (
Expand Down Expand Up @@ -276,8 +282,9 @@ const BaseNumberPanel = ({
const handleChange = (valueAsNumber: number) => {
if (Number.isNaN(valueAsNumber)) return;
setValue(valueAsNumber);
setter(settingKeys, valueAsNumber);
syncToBlock?.(valueAsNumber);
refreshConfigTree();
setter(settingKeys, valueAsNumber);
onChange?.(valueAsNumber);
};

Expand Down Expand Up @@ -323,8 +330,9 @@ const BaseSelectPanel = ({
const handleChange = (e: ChangeEvent<HTMLSelectElement>) => {
const newValue = e.target.value;
setValue(newValue);
setter(settingKeys, newValue);
syncToBlock?.(newValue);
refreshConfigTree();
setter(settingKeys, newValue);
Comment thread
sid597 marked this conversation as resolved.
};

return (
Expand Down Expand Up @@ -400,6 +408,7 @@ const BaseMultiTextPanel = ({
},
});
childUidsRef.current = [...childUidsRef.current, valueUid];
refreshConfigTree();
}
}
};
Expand All @@ -408,7 +417,6 @@ const BaseMultiTextPanel = ({
// eslint-disable-next-line @typescript-eslint/naming-convention
const newValues = values.filter((_, i) => i !== index);
setValues(newValues);
setter(settingKeys, newValues);
onChange?.(newValues);

if (hasBlockSync) {
Expand All @@ -420,7 +428,9 @@ const BaseMultiTextPanel = ({
// eslint-disable-next-line @typescript-eslint/naming-convention
(_, i) => i !== index,
);
refreshConfigTree();
Comment thread
sid597 marked this conversation as resolved.
}
setter(settingKeys, newValues);
};

const handleKeyDown = (e: React.KeyboardEvent) => {
Expand Down
50 changes: 39 additions & 11 deletions apps/roam/src/components/settings/utils/accessors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,24 @@ import { PERSONAL_KEYS, QUERY_KEYS, GLOBAL_KEYS } from "./settingKeys";
const isRecord = (value: unknown): value is Record<string, unknown> =>
typeof value === "object" && value !== null && !Array.isArray(value);

const deepEqual = (a: unknown, b: unknown): boolean => {
if (a === b) return true;
const isEmpty = (v: unknown) => v === undefined || v === "" || v === false;
Comment thread
sid597 marked this conversation as resolved.
Outdated
if (isEmpty(a) && isEmpty(b)) return true;
Comment thread
sid597 marked this conversation as resolved.
Outdated
if (a == null || b == null) return a === b;
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length) return false;
return a.every((v, i) => deepEqual(v, b[i]));
}
if (isRecord(a) && isRecord(b)) {
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
return keysA.every((k) => k in b && deepEqual(a[k], b[k]));
}
return false;
};

const unwrapSchema = (schema: z.ZodTypeAny): z.ZodTypeAny => {
let current = schema;
let didUnwrap = true;
Expand Down Expand Up @@ -444,7 +462,10 @@ const getLegacyGlobalSetting = (keys: string[]): unknown => {
};

const getLegacyQuerySettingByParentUid = (parentUid: string) => {
const scratchNode = getSubTree({ parentUid, key: "scratch" });
const scratchNode = getSubTree({
tree: getBasicTreeByParentUid(parentUid),
key: "scratch",
});
const conditionsNode = getSubTree({
tree: scratchNode.children,
key: "conditions",
Expand Down Expand Up @@ -514,6 +535,9 @@ const getLegacyDiscourseNodeSetting = (
}).children;
const indexUid = getSubTree({ tree, key: "Index" }).uid;
const specificationUid = getSubTree({ tree, key: "Specification" }).uid;
const specificationQuery = specificationUid
? getLegacyQuerySettingByParentUid(specificationUid)
: DEFAULT_LEGACY_QUERY;

const legacySettings = {
type: nodeUid,
Expand Down Expand Up @@ -542,11 +566,11 @@ const getLegacyDiscourseNodeSetting = (
: DEFAULT_LEGACY_QUERY,
specification: {
enabled: specificationUid
? !!getSubTree({ parentUid: specificationUid, key: "enabled" }).uid
? getBasicTreeByParentUid(specificationUid).some(
(c) => c.text === "enabled",
)
Comment thread
sid597 marked this conversation as resolved.
: false,
query: specificationUid
? getLegacyQuerySettingByParentUid(specificationUid)
: DEFAULT_LEGACY_QUERY,
query: specificationQuery,
},
};

Expand Down Expand Up @@ -803,7 +827,7 @@ export const getGlobalSetting = <T = unknown>(
const settings = getGlobalSettings();
const blockPropsValue = readPathValue(settings, keys);
const legacyValue = getLegacyGlobalSetting(keys);
if (JSON.stringify(blockPropsValue) !== JSON.stringify(legacyValue)) {
if (!deepEqual(blockPropsValue, legacyValue)) {
console.warn(
`[DG Dual-Read] Mismatch at Global > ${formatSettingPath(keys)}`,
{ blockProps: blockPropsValue, legacy: legacyValue },
Expand Down Expand Up @@ -875,7 +899,7 @@ export const getPersonalSetting = <T = unknown>(
const settings = getPersonalSettings();
const blockPropsValue = readPathValue(settings, keys);
const legacyValue = getLegacyPersonalSetting(keys);
if (JSON.stringify(blockPropsValue) !== JSON.stringify(legacyValue)) {
if (!deepEqual(blockPropsValue, legacyValue)) {
console.warn(
`[DG Dual-Read] Mismatch at Personal > ${formatSettingPath(keys)}`,
{ blockProps: blockPropsValue, legacy: legacyValue },
Expand Down Expand Up @@ -912,11 +936,13 @@ export const setPersonalSetting = (keys: string[], value: json): void => {
});
};

const getRawDiscourseNodeBlockProps = (nodeType: string): json | undefined => {
const getRawDiscourseNodeBlockProps = (
nodeType: string,
): Record<string, json> | undefined => {
let pageUid = nodeType;
let blockProps = getBlockPropsByUid(pageUid, []);

if (!blockProps || Object.keys(blockProps).length === 0) {
if (!isRecord(blockProps) || Object.keys(blockProps).length === 0) {
const lookedUpUid = getPageUidByPageTitle(
`${DISCOURSE_NODE_PAGE_PREFIX}${nodeType}`,
);
Expand All @@ -926,7 +952,9 @@ const getRawDiscourseNodeBlockProps = (nodeType: string): json | undefined => {
}
}

return blockProps;
return isRecord(blockProps) && Object.keys(blockProps).length > 0
? (blockProps as Record<string, json>)
: undefined;
};

export const getDiscourseNodeSettings = (
Expand Down Expand Up @@ -959,7 +987,7 @@ export const getDiscourseNodeSetting = <T = unknown>(
const settings = getDiscourseNodeSettings(nodeType);
const blockPropsValue = settings ? readPathValue(settings, keys) : undefined;
const legacyValue = getLegacyDiscourseNodeSetting(nodeType, keys);
if (JSON.stringify(blockPropsValue) !== JSON.stringify(legacyValue)) {
if (!deepEqual(blockPropsValue, legacyValue)) {
console.warn(
`[DG Dual-Read] Mismatch at Discourse Node (${nodeType}) > ${formatSettingPath(keys)}`,
{ blockProps: blockPropsValue, legacy: legacyValue },
Expand Down
Loading
Loading