Skip to content

fix: enhance connection storage handling and improve UI accessibility#1616

Merged
shahar-biron merged 2 commits intostagingfrom
fix-ai-comments
Apr 9, 2026
Merged

fix: enhance connection storage handling and improve UI accessibility#1616
shahar-biron merged 2 commits intostagingfrom
fix-ai-comments

Conversation

@Anchel123
Copy link
Copy Markdown
Contributor

@Anchel123 Anchel123 commented Apr 9, 2026

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved session cleanup on logout with better storage management.
    • Added validation for search result limits (constrained to 10–50 items).
    • Enhanced browser environment detection for data persistence.
  • New Features

    • Better handling of data persistence across sessions with connection-based scoping.
    • Automatic migration of legacy user settings.
  • Improvements

    • Enhanced accessibility for settings controls with improved label associations.
    • Updated default UI values for table layouts and search settings.
  • Chores

    • Bumped version to 1.9.4.
    • Updated chart library to 5.6.0.
    • Reorganized dependencies.

@overcut-ai
Copy link
Copy Markdown

overcut-ai bot commented Apr 9, 2026

Completed Working on "Code Review"

✅ Review publishing complete: comments posted from all chunks and final review submitted (COMMENT).

✅ Workflow completed successfully.


👉 View complete log

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
falkordb-browser Ready Ready Preview, Comment Apr 9, 2026 10:24am

Request Review

Copy link
Copy Markdown

@overcut-ai overcut-ai bot left a comment

Choose a reason for hiding this comment

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

Thanks for the updates. Consolidated review summary based on posted findings:

  • Total by importance: 4 MAJOR, 1 MINOR (0 BLOCKER, 0 CRITICAL)
  • Affected files: app/providers.tsx, app/graph/Chat.tsx, app/graph/graphInfo.tsx, package.json

Key themes

  1. Connection-scoped persistence lifecycle risks: initialization/teardown sequencing can skip valid data load or leave scoped data behind across sessions.
  2. State/input hardening gaps: numeric settings restoration from storage lacks robust validation for some fields.
  3. Behavior/performance safety: repeated in-render sorting and dependency changes (ECharts downgrade) need guardrails to avoid regressions.

Recommended next steps

  1. Ensure chat history loading re-runs when connection prefix becomes ready (not only on graph-name changes).
  2. Harden all restored numeric UI settings with finite/range validation + defaults.
  3. Expand logout cleanup to remove all relevant connection-scoped keys before clearing prefix.
  4. Memoize or precompute property key sorting to avoid repeated render cost on large datasets.
  5. Add CI/runtime chart smoke coverage (or equivalent verification) for the ECharts 6→5 downgrade and document constraints.


// Load messages and cypher only preference for current graph on mount
useEffect(() => {
if (!getConnectionPrefix()) return;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[major]: The new early return (if (!getConnectionPrefix()) return;) avoids unscoped reads, but it can also permanently skip chat-history initialization when this effect runs before the connection prefix is set. Since the effect appears to run only on graph-name changes, users may miss valid saved history for the active graph after login/session hydration.

Suggested fix: Trigger history loading when prefix readiness changes (e.g., include a provider prefixReady signal in effect dependencies) or defer loading until prefix is initialized instead of returning without a re-run path.

setRowHeight(parseInt(localStorage.getItem("rowHeight") || "40", 10));
setRowHeightExpandMultiple(parseInt(localStorage.getItem("rowHeightExpandMultiple") || "3", 10));
setMaxItemsForSearch(parseInt(localStorage.getItem("maxItemsForSearch") || "20", 10));
const parsedMaxItems = parseInt(localStorage.getItem("maxItemsForSearch") || "20", 10);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[major]: UI settings loaded from localStorage are parsed with parseInt and assigned directly for column/row sizing, so invalid persisted values (e.g. non-numeric strings) produce NaN and can break initial slider/value rendering before user interaction. This regresses initial UX stability for users with corrupted or legacy storage.

Suggested fix: Apply the same finite-and-range guard used for maxItemsForSearch to columnWidth, rowHeight, and rowHeightExpandMultiple (fallback to defaults when parse fails).

} else {
// Clean up scoped data before clearing the prefix,
// so removeConnectionItem can still resolve the scoped key.
removeConnectionItem("savedContent");
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[major]: On sign-out, only scoped savedContent is removed before clearing the prefix. Connection-scoped graph keys like chat-* and cypherOnly-* are not cleared, so old per-connection data can persist across sessions on shared browsers.

Suggested fix: During logout, iterate localStorage keys with the active connection prefix and remove all scoped app keys (or at least include query history, chat-*, and cypherOnly-*) before calling `clearConnectionPrefix().

<ul className="flex flex-wrap gap-2 p-2 overflow-auto">
{
PropertyKeys && PropertyKeys.filter(key => key.toLowerCase().includes(propertyKeysSearch.toLowerCase())).map((key) => (
PropertyKeys && PropertyKeys.filter(key => key.toLowerCase().includes(propertyKeysSearch.toLowerCase())).sort((a, b) => a.localeCompare(b)).map((key) => (
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[minor]: Sorting PropertyKeys inside render adds O(n log n) work on every re-render, which can noticeably slow the panel for large metadata sets even when the underlying keys are unchanged.

Suggested fix: Memoize the filtered+sorted list with useMemo keyed by PropertyKeys and propertyKeysSearch, or pre-sort once when PropertyKeys changes.

"date-fns": "^4.1.0",
"depcheck": "^1.4.7",
"echarts": "^6.0.0",
"echarts": "^5.6.0",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[major]: The dependency was downgraded from ECharts 6 to 5 while echarts-for-react and chart code may rely on v6 APIs/behaviors. This can cause runtime chart failures after deployment if any v6-only options or defaults are in use.

Suggested fix: Add/extend chart smoke tests (or a quick runtime verification in CI) that render representative charts against ECharts 5, and document the downgrade rationale/constraints in the PR or changelog.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 9, 2026

Walkthrough

This PR introduces SSR safety guards to connection storage operations, extends migration logic to handle legacy graph-specific keys, updates default values for layout and search settings, gates persistence behind connection readiness checks, and improves form accessibility.

Changes

Cohort / File(s) Summary
Connection Storage Foundation
lib/connection-storage.ts
Added SSR/browser environment guard (isBrowser) to prevent window access during server-side rendering. Extended migrateToScopedStorage with a second phase that scans and migrates legacy chat-* and cypherOnly-* keys to connection-prefixed equivalents.
Authentication and Chat Flow
app/loginVerification.tsx, app/graph/Chat.tsx
Removed redundant removeConnectionItem call from login verification (now handled in providers). Added connection prefix guard to Chat mount-time storage loading to skip reading persisted messages if prefix is unavailable.
Provider and Settings State
app/providers.tsx, app/graph/graphInfo.tsx
Updated default state values for table layout (25/40 instead of 0) and search settings (20 items instead of 0). Gated query/history persistence behind prefixReady flag. Added clamped parsing for maxItemsForSearch (bounds [10, 50]). Extended useEffect dependency arrays to include maxItemsForSearch and sort PropertyKeys alphabetically.
UI Accessibility
app/settings/browserSettings.tsx
Added explicit id attributes to form labels and corresponding aria-labelledby attributes to Slider components, improving semantic accessibility relationships.
Dependencies
package.json
Bumped version to 1.9.4, downgraded echarts from ^6.0.0 to ^5.6.0, moved playwright to devDependencies.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

A connection takes shape with careful guards,
SSR-safe and migration-blessed,
Default values settle, accessibility praised,
Storage flows where prefixes nest,
Refactored with purpose, tested with zest 🔐

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: connection storage enhancements (added removeConnectionItem, SSR guards, migration logic) and UI accessibility improvements (added aria-labelledby attributes to sliders).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-ai-comments

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
Copy Markdown
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.

🧹 Nitpick comments (1)
lib/connection-storage.ts (1)

86-105: Migration loop correctly handles index shifts, but consider null-safe access.

The i-- after removeItem properly compensates for array shrinkage. However, line 97 uses a non-null assertion that could theoretically fail if the key is removed between the startsWith check and getItem.

🛡️ Suggested safer alternative
       if (key.startsWith(p)) {
         const scopedKey = prefixed(key);
         if (localStorage.getItem(scopedKey) === null) {
-          localStorage.setItem(scopedKey, localStorage.getItem(key)!);
+          const value = localStorage.getItem(key);
+          if (value !== null) {
+            localStorage.setItem(scopedKey, value);
+          }
         }
         localStorage.removeItem(key);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/connection-storage.ts` around lines 86 - 105, The migration loop in
connection-storage.ts uses a non-null assertion when calling
localStorage.getItem(key) inside the SCOPED_KEY_PREFIXES handling which could
fail if the entry disappears between checks; update the logic in that block (the
loop referencing localStorage, SCOPED_KEY_PREFIXES and the prefixed(...) helper)
to read the value into a local variable first (const value =
localStorage.getItem(key)), check value !== null before calling
localStorage.setItem(scopedKey, value), and then call
localStorage.removeItem(key) and decrement i; this avoids the non-null assertion
and prevents double reads.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lib/connection-storage.ts`:
- Around line 86-105: The migration loop in connection-storage.ts uses a
non-null assertion when calling localStorage.getItem(key) inside the
SCOPED_KEY_PREFIXES handling which could fail if the entry disappears between
checks; update the logic in that block (the loop referencing localStorage,
SCOPED_KEY_PREFIXES and the prefixed(...) helper) to read the value into a local
variable first (const value = localStorage.getItem(key)), check value !== null
before calling localStorage.setItem(scopedKey, value), and then call
localStorage.removeItem(key) and decrement i; this avoids the non-null assertion
and prevents double reads.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9fb19488-5ee2-4cd9-ba65-3841a65d9686

📥 Commits

Reviewing files that changed from the base of the PR and between ed3b253 and cf7a507.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (7)
  • app/graph/Chat.tsx
  • app/graph/graphInfo.tsx
  • app/loginVerification.tsx
  • app/providers.tsx
  • app/settings/browserSettings.tsx
  • lib/connection-storage.ts
  • package.json

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 9, 2026

🔒 Trivy Security Scan Results


Report Summary

┌───────────────────────────────────────────────────────────────────────────┬──────────┬─────────────────┐
│                                  Target                                   │   Type   │ Vulnerabilities │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ falkordb/falkordb-browser:test (alpine 3.22.3)                            │  alpine  │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@falkordb/text-to-cypher/package.json                    │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@img/colour/package.json                                 │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@img/sharp-libvips-linux-x64/package.json                │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@img/sharp-libvips-linuxmusl-x64/package.json            │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@img/sharp-linux-x64/package.json                        │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@img/sharp-linuxmusl-x64/package.json                    │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@js-temporal/polyfill/package.json                       │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@next/env/package.json                                   │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@redis/bloom/package.json                                │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@redis/client/dist/package.json                          │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@redis/client/package.json                               │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@redis/json/package.json                                 │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@redis/search/package.json                               │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@redis/time-series/package.json                          │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/@swc/helpers/package.json                                │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/client-only/package.json                                 │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/cluster-key-slot/package.json                            │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/detect-libc/package.json                                 │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/falkordb/package.json                                    │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/jsbi/package.json                                        │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/lodash/package.json                                      │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/next/dist/compiled/@edge-runtime/cookies/package.json    │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/next/dist/compiled/@edge-runtime/ponyfill/package.json   │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/next/dist/compiled/@edge-runtime/primitives/package.json │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/next/dist/compiled/react-is/package.json                 │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/next/dist/compiled/regenerator-runtime/package.json      │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/next/package.json                                        │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/react-dom/package.json                                   │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/react/package.json                                       │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/redis/package.json                                       │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/semver/package.json                                      │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/sharp/package.json                                       │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/node_modules/styled-jsx/package.json                                  │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ app/package.json                                                          │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ opt/yarn-v1.22.22/package.json                                            │ node-pkg │        0        │
├───────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────┤
│ usr/local/lib/node_modules/corepack/package.json                          │ node-pkg │        0        │
└───────────────────────────────────────────────────────────────────────────┴──────────┴─────────────────┘
Legend:
- '-': Not scanned
- '0': Clean (no security findings detected)


@shahar-biron shahar-biron merged commit b4cc802 into staging Apr 9, 2026
19 checks passed
@shahar-biron shahar-biron deleted the fix-ai-comments branch April 9, 2026 10:33
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.

2 participants