Skip to content

Conversation

@sid597
Copy link
Collaborator

@sid597 sid597 commented Dec 12, 2025

https://www.loom.com/share/e0af00458a4346798f59d9ca5dc437ab

Summary by CodeRabbit

  • Bug Fixes

    • Improved reliability of reference resolution and display in sidebar sections
    • Enhanced accuracy of page title and block reference rendering
  • Refactor

    • Internal optimization of sidebar target handling and reference logic

✏️ Tip: You can customize this high-level summary in your review settings.

@linear
Copy link

linear bot commented Dec 12, 2025

@supabase
Copy link

supabase bot commented Dec 12, 2025

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

Copy link
Collaborator Author

sid597 commented Dec 12, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

@sid597 sid597 changed the title save block uids of pages instead of page titles itself ENG-1127 update left sidebar when page titles change Dec 12, 2025
@sid597 sid597 changed the title ENG-1127 update left sidebar when page titles change ENG-1127 fix: update left sidebar when page titles change Dec 12, 2025
@sid597 sid597 marked this pull request as ready for review December 12, 2025 17:16
@sid597
Copy link
Collaborator Author

sid597 commented Dec 12, 2025

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 12, 2025

✅ Actions performed

Full review triggered.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 12, 2025

📝 Walkthrough

Walkthrough

These changes refactor the Left Sidebar components to use UID-based resolution for pages and blocks instead of title-based lookup, introducing getPageTitleByPageUid and getPageUidByPageTitle functions to ensure consistent title resolution and reference handling across target opening, label display, and favorites migration.

Changes

Cohort / File(s) Summary
Left Sidebar View Logic
apps/roam/src/components/LeftSidebarView.tsx
Refactored openTarget to accept and use targetUid for block/page navigation instead of title-based resolution; updated SectionChildren labels to resolve page titles via getPageTitleByPageUid or block text via getTextByBlockUid; reworked favorites migration to retrieve and work with block UIDs instead of titles.
Global Settings Page Management
apps/roam/src/components/settings/LeftSidebarGlobalSettings.tsx
Updated page display to show resolved titles via getPageTitleByPageUid; added getPageUidByPageTitle resolution for page addition, duplicate checking, and block creation; updated isAddButtonDisabled validation to use resolved UIDs.
Personal Settings Child Items
apps/roam/src/components/settings/LeftSidebarPersonalSettings.tsx
Replaced direct child text with resolved page UID via getPageUidByPageTitle, with fallback to trimmed child name; expanded child display logic to resolve titles using getPageTitleByPageUid or block text extraction.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

  • Verify UID resolution correctness across all three files, particularly in getPageUidByPageTitle lookups and fallback chains
  • Review the updated favorites migration logic in LeftSidebarView to ensure UIDs are properly collected and mapped
  • Confirm SectionChildren label resolution handles both page and block references correctly without regression
  • Check for edge cases in duplicate detection and comparison logic now using UIDs instead of titles

Possibly related PRs

Pre-merge checks

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'ENG-1127 fix: update left sidebar when page titles change' accurately reflects the main objective of the changeset, which focuses on resolving page and block references by UID to ensure the left sidebar updates correctly when titles change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
apps/roam/src/components/LeftSidebarView.tsx (1)

489-500: Use sequential insertion to preserve favorites order during migration. Promise.all executes block insertions in parallel, which can cause favorites to appear out of order in Roam due to varying network latency. Since this is a one-time migration, sequential execution is preferable:

-    await Promise.all(
-      newFavorites.map(({ uid }) =>
-        createBlock({ parentUid: childrenUid, node: { text: uid } }),
-      ),
-    );
+    for (const { uid } of newFavorites) {
+      // eslint-disable-next-line no-await-in-loop
+      await createBlock({ parentUid: childrenUid, node: { text: uid } });
+    }
apps/roam/src/components/settings/LeftSidebarPersonalSettings.tsx (1)

146-175: Reject storing titles as child references; require valid page UIDs.
Line 154 currently falls back to childName.trim(), which stores a title string instead of a UID. This breaks the downstream SectionChildren component, which calls parseReference(child.text) and expects a valid reference syntax. When a page doesn't exist, reject the operation instead of storing invalid data.

-        const targetUid = getPageUidByPageTitle(childName) || childName.trim();
+        const normalized = childName.trim();
+        const targetUid = getPageUidByPageTitle(normalized);
+        if (!targetUid) {
+          renderToast({
+            content: `Page "${normalized}" not found`,
+            intent: "danger",
+            id: "add-child-page-not-found",
+          });
+          return;
+        }
apps/roam/src/components/settings/LeftSidebarGlobalSettings.tsx (1)

176-210: Guard targetUid before writing; Enter key bypasses button validation and can create empty blocks.

Line 182's !pageName check only catches falsy values—whitespace-only input (e.g., " ") passes through. Then getPageUidByPageTitle returns "" at line 180, but the onConfirm callback on line 317 invokes addPage regardless of the button's disabled state, allowing line 190 to write an empty block text to the database. Trim input and guard the empty targetUid to prevent this and provide clear user feedback.

-      const targetUid = getPageUidByPageTitle(pageName);
+      const normalized = pageName.trim();
+      const targetUid = getPageUidByPageTitle(normalized);
+      if (!targetUid) {
+        renderToast({
+          content: `Page "${normalized}" not found`,
+          intent: "warning",
+          id: "add-global-page-not-found",
+        });
+        return;
+      }
       if (pages.some((p) => p.text === targetUid)) {
         console.warn(`Page "${pageName}" already exists in global section`);
         return;
       }
🧹 Nitpick comments (2)
apps/roam/src/components/settings/LeftSidebarGlobalSettings.tsx (1)

236-240: Disable logic is good; consider trimming to match addPage.

apps/roam/src/components/LeftSidebarView.tsx (1)

59-85: UID-based open flow looks correct; consider adding an explicit return type.

-const openTarget = async (e: React.MouseEvent, targetUid: string) => {
+const openTarget = async (
+  e: React.MouseEvent,
+  targetUid: string,
+): Promise<void> => {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 193e67d and 3cb07ce.

📒 Files selected for processing (3)
  • apps/roam/src/components/LeftSidebarView.tsx (6 hunks)
  • apps/roam/src/components/settings/LeftSidebarGlobalSettings.tsx (5 hunks)
  • apps/roam/src/components/settings/LeftSidebarPersonalSettings.tsx (4 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/main.mdc)

**/*.{ts,tsx}: Use Tailwind CSS for styling where possible
When refactoring inline styles, use tailwind classes
Prefer type over interface in TypeScript
Use explicit return types for functions
Avoid any types when possible
Prefer arrow functions over regular function declarations
Use named parameters (object destructuring) when a function has more than 2 parameters
Use PascalCase for components and types
Use camelCase for variables and functions
Use UPPERCASE for constants
Function names should describe their purpose clearly
Prefer early returns over nested conditionals for better readability

Files:

  • apps/roam/src/components/settings/LeftSidebarGlobalSettings.tsx
  • apps/roam/src/components/LeftSidebarView.tsx
  • apps/roam/src/components/settings/LeftSidebarPersonalSettings.tsx
apps/roam/**/*.{js,ts,tsx,jsx,json}

📄 CodeRabbit inference engine (.cursor/rules/roam.mdc)

Prefer existing dependencies from package.json when working on the Roam Research extension

Files:

  • apps/roam/src/components/settings/LeftSidebarGlobalSettings.tsx
  • apps/roam/src/components/LeftSidebarView.tsx
  • apps/roam/src/components/settings/LeftSidebarPersonalSettings.tsx
apps/roam/**/*.{ts,tsx,jsx,js,css,scss}

📄 CodeRabbit inference engine (.cursor/rules/roam.mdc)

Use BlueprintJS 3 components and Tailwind CSS for platform-native UI in the Roam Research extension

Files:

  • apps/roam/src/components/settings/LeftSidebarGlobalSettings.tsx
  • apps/roam/src/components/LeftSidebarView.tsx
  • apps/roam/src/components/settings/LeftSidebarPersonalSettings.tsx
apps/roam/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/roam.mdc)

apps/roam/**/*.{ts,tsx,js,jsx}: Use the roamAlphaApi docs from https://roamresearch.com/#/app/developer-documentation/page/tIaOPdXCj when implementing Roam functionality
Use Roam Depot/Extension API docs from https://roamresearch.com/#/app/developer-documentation/page/y31lhjIqU when implementing extension functionality

Files:

  • apps/roam/src/components/settings/LeftSidebarGlobalSettings.tsx
  • apps/roam/src/components/LeftSidebarView.tsx
  • apps/roam/src/components/settings/LeftSidebarPersonalSettings.tsx
apps/roam/**

📄 CodeRabbit inference engine (.cursor/rules/roam.mdc)

Implement the Discourse Graph protocol in the Roam Research extension

Files:

  • apps/roam/src/components/settings/LeftSidebarGlobalSettings.tsx
  • apps/roam/src/components/LeftSidebarView.tsx
  • apps/roam/src/components/settings/LeftSidebarPersonalSettings.tsx
🧠 Learnings (7)
📓 Common learnings
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 534
File: apps/roam/src/utils/createReifiedBlock.ts:40-48
Timestamp: 2025-11-05T21:57:14.909Z
Learning: In the discourse-graph repository, the function `getPageUidByPageTitle` from `roamjs-components/queries/getPageUidByPageTitle` is a synchronous function that returns a string directly (the page UID or an empty string if not found), not a Promise. It should be called without `await`.
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 559
File: apps/roam/src/utils/findDiscourseNode.ts:37-39
Timestamp: 2025-12-07T20:54:19.988Z
Learning: In apps/roam/src/utils/findDiscourseNode.ts, the function findDiscourseNodeByTitleAndUid accepts both uid and title parameters where uid is primarily used for cache access (as the cache key) while title is used for the actual matching via matchDiscourseNode. This design reflects the pattern where downstream, the uid is mostly used to fetch the title, so the function caches by uid but matches by title.
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 0
File: :0-0
Timestamp: 2025-06-25T22:56:17.522Z
Learning: In the Roam discourse-graph system, the existence of the configuration page (identified by DISCOURSE_CONFIG_PAGE_TITLE) and its corresponding UID is a system invariant. The code can safely assume this page will always exist, so defensive null checks are not needed when using `getPageUidByPageTitle(DISCOURSE_CONFIG_PAGE_TITLE)`.
📚 Learning: 2025-12-07T20:54:19.988Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 559
File: apps/roam/src/utils/findDiscourseNode.ts:37-39
Timestamp: 2025-12-07T20:54:19.988Z
Learning: In apps/roam/src/utils/findDiscourseNode.ts, the function findDiscourseNodeByTitleAndUid accepts both uid and title parameters where uid is primarily used for cache access (as the cache key) while title is used for the actual matching via matchDiscourseNode. This design reflects the pattern where downstream, the uid is mostly used to fetch the title, so the function caches by uid but matches by title.

Applied to files:

  • apps/roam/src/components/settings/LeftSidebarGlobalSettings.tsx
  • apps/roam/src/components/LeftSidebarView.tsx
  • apps/roam/src/components/settings/LeftSidebarPersonalSettings.tsx
📚 Learning: 2025-06-25T22:56:17.522Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 0
File: :0-0
Timestamp: 2025-06-25T22:56:17.522Z
Learning: In the Roam discourse-graph system, the existence of the configuration page (identified by DISCOURSE_CONFIG_PAGE_TITLE) and its corresponding UID is a system invariant. The code can safely assume this page will always exist, so defensive null checks are not needed when using `getPageUidByPageTitle(DISCOURSE_CONFIG_PAGE_TITLE)`.

Applied to files:

  • apps/roam/src/components/settings/LeftSidebarGlobalSettings.tsx
  • apps/roam/src/components/LeftSidebarView.tsx
📚 Learning: 2025-11-05T21:57:14.909Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 534
File: apps/roam/src/utils/createReifiedBlock.ts:40-48
Timestamp: 2025-11-05T21:57:14.909Z
Learning: In the discourse-graph repository, the function `getPageUidByPageTitle` from `roamjs-components/queries/getPageUidByPageTitle` is a synchronous function that returns a string directly (the page UID or an empty string if not found), not a Promise. It should be called without `await`.

Applied to files:

  • apps/roam/src/components/settings/LeftSidebarGlobalSettings.tsx
  • apps/roam/src/components/LeftSidebarView.tsx
  • apps/roam/src/components/settings/LeftSidebarPersonalSettings.tsx
📚 Learning: 2025-11-25T00:52:41.934Z
Learnt from: CR
Repo: DiscourseGraphs/discourse-graph PR: 0
File: .cursor/rules/roam.mdc:0-0
Timestamp: 2025-11-25T00:52:41.934Z
Learning: Applies to apps/roam/**/*.{ts,tsx,js,jsx} : Use the roamAlphaApi docs from https://roamresearch.com/#/app/developer-documentation/page/tIaOPdXCj when implementing Roam functionality

Applied to files:

  • apps/roam/src/components/settings/LeftSidebarGlobalSettings.tsx
  • apps/roam/src/components/LeftSidebarView.tsx
📚 Learning: 2025-11-25T00:52:41.934Z
Learnt from: CR
Repo: DiscourseGraphs/discourse-graph PR: 0
File: .cursor/rules/roam.mdc:0-0
Timestamp: 2025-11-25T00:52:41.934Z
Learning: Applies to apps/roam/**/*.{ts,tsx,jsx,js,css,scss} : Use BlueprintJS 3 components and Tailwind CSS for platform-native UI in the Roam Research extension

Applied to files:

  • apps/roam/src/components/LeftSidebarView.tsx
📚 Learning: 2025-06-22T10:40:52.752Z
Learnt from: sid597
Repo: DiscourseGraphs/discourse-graph PR: 232
File: apps/roam/src/utils/getAllDiscourseNodesSince.ts:18-31
Timestamp: 2025-06-22T10:40:52.752Z
Learning: In apps/roam/src/utils/getAllDiscourseNodesSince.ts, the user confirmed that querying for `?title` with `:node/title` and mapping it to the `text` field in the DiscourseGraphContent type is the correct implementation for retrieving discourse node content from Roam Research, despite it appearing to query page titles rather than block text content.

Applied to files:

  • apps/roam/src/components/LeftSidebarView.tsx
🔇 Additional comments (5)
apps/roam/src/components/settings/LeftSidebarPersonalSettings.tsx (2)

28-28: Import addition looks consistent with the UID-based display refactor.


373-384: Label resolution is a good compatibility bridge for legacy stored values.

apps/roam/src/components/settings/LeftSidebarGlobalSettings.tsx (1)

18-19: Import addition looks fine.

apps/roam/src/components/LeftSidebarView.tsx (2)

43-43: Import addition looks consistent with the new label-resolution path.


439-447: Migration switching to storing UIDs is aligned with the rename-safe approach.

@sid597 sid597 requested a review from mdroidian December 12, 2025 19:25
Copy link
Contributor

@mdroidian mdroidian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally looks good, but unfortunately merging this will break sidebar for anyone already using it.

Unfortunately, I think we need to include the migration/backwards compatibility in this PR. Unless no pilots are currently using the left sidebar (but I don't think that is the case, although I could be wrong).

If you'd like it to be a separate task that gets merged into this PR, that works for me.

@sid597 sid597 force-pushed the eng-1127-left-sidebar-doesnt-update-when-pages-are-renamed branch from 3cb07ce to 8686da6 Compare December 15, 2025 09:04
@sid597
Copy link
Collaborator Author

sid597 commented Dec 15, 2025

@sid597 sid597 requested a review from mdroidian December 15, 2025 11:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants