ENG-1472: Refactor BlockPropSettingPanels to add accessor-backed default reads (with initialValue fallback)#813
Conversation
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
📝 WalkthroughWalkthroughThis PR refactors BlockPropSettingPanels.tsx to introduce a Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/roam/src/components/settings/components/BlockPropSettingPanels.tsx (1)
473-483: Consider logging caught errors for debuggability.The bare
catchsilently swallows all exceptions — including unexpected ones (e.g.,TypeErrorfrom a bug inreadPathValue). This is a reasonable resilience trade-off for UI code, but aconsole.warnwould make misconfigured keys or accessor bugs much easier to diagnose.Proposed fix
const readWithFallback = <T,>( reader: () => T | undefined, fallback?: T, ): T | undefined => { try { const value = reader(); return value ?? fallback; - } catch { + } catch (e) { + console.warn("[readWithFallback] accessor threw, using fallback:", e); return fallback; } };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/roam/src/components/settings/components/BlockPropSettingPanels.tsx` around lines 473 - 483, The readWithFallback function currently swallows all exceptions silently; update it to catch the error into a variable and call console.warn (or processLogger if available) with a concise message including the error and context (e.g., "readWithFallback failed" and the thrown error) before returning the fallback; keep existing behavior of returning fallback on exceptions and preserve the reader/fallback signature so callers of readWithFallback continue to work unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@apps/roam/src/components/settings/components/BlockPropSettingPanels.tsx`:
- Around line 473-483: The readWithFallback function currently swallows all
exceptions silently; update it to catch the error into a variable and call
console.warn (or processLogger if available) with a concise message including
the error and context (e.g., "readWithFallback failed" and the thrown error)
before returning the fallback; keep existing behavior of returning fallback on
exceptions and preserve the reader/fallback signature so callers of
readWithFallback continue to work unchanged.
5a02381 to
b67fd5f
Compare
c635833 to
b1ace1a
Compare
adf5fb5 to
75d22ad
Compare
c90e2c8 to
3b1643c
Compare
75d22ad to
cc8a3f2
Compare
cc8a3f2 to
c7a64a1
Compare
3b1643c to
ee38a5f
Compare
| settingKeys={[featureKey as string]} | ||
| setter={featureFlagSetter} | ||
| initialValue={initialValue} | ||
| initialValue={readWithFallback(() => getFeatureFlag(featureKey), initialValue)} |
There was a problem hiding this comment.
🔴 readWithFallback never falls back for FeatureFlagPanel because getFeatureFlag always returns boolean
The FeatureFlagPanel component uses readWithFallback(() => getFeatureFlag(featureKey), initialValue) to compute the initial value. However, getFeatureFlag always returns a boolean (never undefined or null) because FeatureFlagsSchema has .default(false) for every field. Since readWithFallback uses value ?? fallback, and false ?? initialValue evaluates to false, the caller's initialValue fallback is effectively dead code under normal conditions.
Root cause and impact
getFeatureFlag at apps/roam/src/components/settings/utils/accessors.ts:668-671 calls getFeatureFlags() which parses block props with FeatureFlagsSchema.parse(blockProps || {}). The schema defines all flags with .default(false), so even when no block props exist, the parse returns { "Enable left sidebar": false, ... }.
In readWithFallback at line 494-495:
const value = reader(); // returns false (not undefined)
return value ?? fallback; // false ?? initialValue → falseThis means the legacy initialValue passed by callers (e.g., settings.leftSidebarEnabled.value in GeneralSettings.tsx:46) is ignored. For users who had a feature flag enabled in the legacy system but whose block props were initialized with schema defaults (false), the checkbox will incorrectly show as unchecked.
For example, a user with the left sidebar enabled via the legacy block tree will see the checkbox unchecked after this change, because block props return false and the legacy initialValue={true} is never used as fallback.
Impact: Feature flag checkboxes may display incorrect initial state for existing users whose flags haven't been migrated to block props, contradicting the PR's stated goal of "with initialValue fallback."
Prompt for agents
In apps/roam/src/components/settings/components/BlockPropSettingPanels.tsx, the readWithFallback function at line 489-499 uses the nullish coalescing operator (??), which only falls back for undefined/null. For getFeatureFlag, which always returns a boolean (false as default from schema), the fallback never triggers.
The fix depends on the desired semantics:
Option A: If the intent is to prefer block props when they have been explicitly set, and fall back to initialValue otherwise, then getFeatureFlag needs to distinguish between "explicitly set to false" and "defaulted to false because no value exists." This would require changing getFeatureFlag (or adding a variant) in apps/roam/src/components/settings/utils/accessors.ts around line 668-671 to return undefined when the block props don't contain an explicit value for the key, rather than returning the schema default.
Option B: If block props are always the source of truth for feature flags (because setFeatureFlag writes to block props), then the initialValue prop on FeatureFlagPanel is unnecessary and should be documented as such, or removed from the FeatureFlagPanel interface to avoid confusion.
Was this helpful? React with 👍 or 👎 to provide feedback.
ee38a5f to
c7c04c6
Compare
0cf1a61 to
d604e8d
Compare
c7c04c6 to
2f2cf80
Compare
d604e8d to
5a6f356
Compare
2f2cf80 to
080ebb1
Compare
…ult reads (with initialValue fallback)
080ebb1 to
f1855a5
Compare

Summary by CodeRabbit