Skip to content

feat(sidebar): show connection identity in connections strip entries - #2563

Open
devy1540 wants to merge 1 commit into
TableProApp:mainfrom
devy1540:feat/workspace-identification
Open

feat(sidebar): show connection identity in connections strip entries#2563
devy1540 wants to merge 1 commit into
TableProApp:mainfrom
devy1540:feat/workspace-identification

Conversation

@devy1540

@devy1540 devy1540 commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Purpose

Fixes #2550.

A connections-strip entry represents a workspace identified by both a connection and the database or schema it is browsing. The visible label only showed the container, so two different connections could render as identical entries.

For example:

Connection Database Visible label before
Production app app
Staging app app

When both connections use the same engine and have no custom connection color, identifying the environment requires hovering over each entry or switching to it first.

What was wrong

WorkspaceRailEntry already carries the full DatabaseConnection and a WorkspaceID keyed by connectionId + container. The identity and navigation models were not losing data. The visible label discarded the connection name whenever a container existed.

Switching, selection, ordering, closing, dragging, and persistence continue to use WorkspaceID, so the fix belongs in the cell presentation rather than in the workspace or connection model.

Why two lines

The obvious version was a single combined label:

Production · app
Staging · app

That still becomes ambiguous in a narrow rail. With middle truncation, connection names that share a prefix and a common container can lose the part that distinguishes them:

podo-prod · gwatop  → pod…atop
podo-stage · gwatop → pod…atop

The connection and container now occupy explicit semantic lines, and each line truncates independently:

podo-prod
gwatop

podo-stage
gwatop

This keeps the connection identity visible without widening the strip or making the label depend on which other workspaces happen to be open.

Changes and intent

Connection-first labels

WorkspaceRailCellView keeps its existing NSTableCellView.textField and renders one attributed value with an explicit semantic line break:

  • first line: connection name
  • second line: database or schema name
  • one line only when the engine has no switchable container
  • primary text at the current sidebar font size
  • secondary text one point smaller, with a minimum size of 10 pt
  • independent middle truncation on both lines

Keeping one native text field preserves AppKit selected-row foreground colors, drag images, expansion tooltips, cell reuse, accessibility ownership, and source-list behavior.

Embedded line separators are flattened for display before the semantic line break is inserted, so imported or legacy values cannot create additional visual rows. A blank connection name falls back to the container without leaving an empty first line. Stored connection and workspace identities are not modified.

Existing rail density

The strip keeps its existing size contracts:

Sidebar size Rail width Row height Icon size
Small 80 pt 52 pt 20 pt
Medium 90 pt 58 pt 24 pt
Large 100 pt 66 pt 28 pt

The icon moves upward within the existing row. The gap before the label is derived from the identity-dot radius, which keeps the dot and text from overlapping at every sidebar size.

The row height, row pitch, scroll snapping, and window minimum width are unchanged.

Type select

Changing the visible text to begin with the connection name would have removed the existing database/schema prefix search if the table continued relying on AppKit default text-field matching.

The rail now matches prefixes of both the connection name and the database or schema name. Matching ignores case, diacritic, and full-width versus half-width differences.

The matcher follows the circular range passed by AppKit:

  • startRow is included
  • endRow is excluded
  • the range can wrap from the last row to the first
  • startRow == endRow means one complete circular scan
  • no match returns -1

A local AppKit probe measured the equal-bound behavior for tables with one and multiple rows. The implementation uses a repeat-and-wrap scan so every candidate is visited exactly once.

Existing behavior preserved

The following continue to use WorkspaceID(connectionId, container) and were not re-keyed by the new presentation:

  • connection and container switching
  • selected-row tracking
  • previous and next workspace commands
  • drag reordering and order persistence
  • middle-click and Cmd+W closing
  • Close Database, Close Schema, and Close Connection
  • disconnect and reconnect
  • scroll snapping and selected-row reveal
  • status glyphs, engine colors, and custom connection-color dots

The tooltip still contains the full connection, host, and container identity. The VoiceOver label still names the connection, typed database or schema, connection state, and optional color.

Documentation

The connections-strip documentation now describes the connection name on the first line, the database or schema on the second line, and prefix type select across both values.

Two stale claims in the section were also corrected:

  • the connection color appears on the identity dot rather than tinting the engine glyph
  • DuckDB is not an unconditional single-entry example because it supports database and schema switching

The change is recorded under [Unreleased] > Changed.

Before / After

Before, two connections that browse the same database show the same visible label:

[MySQL]
app

[MySQL]
app

After, the connection is the primary line and the database or schema is the secondary line:

[MySQL]
Production
app

[MySQL]
Staging
app

Sanitized light and dark screenshots using generic fixtures will be attached before the PR is marked ready for review. No private hosts, accounts, or environment names will be included.

Success criteria

Cell text, type select, and rendering

The following suites cover the presentation and keyboard contracts:

  • WorkspaceRailCellTextTests
  • WorkspaceRailTypeSelectTests
  • WorkspaceRailCellRenderingTests

Covered cases include different connections with one database, one connection with multiple databases, schema workspaces, engines with no container, blank-name fallback, embedded line separators, independent middle truncation, connection and container prefix matching, ordinary and wrapped ranges, excluded end rows, equal-bound circular searches, localized comparisons, empty searches, empty lists, and invalid ranges.

Result after the AppKit circular-range correction:

55 executed
55 passed
0 failed

WorkspaceRailCellRenderingTests builds and rasterizes the real WorkspaceRailCellView. It verifies that the reported production/staging class of entries produces visibly different rows, the label stays within all three row sizes, the identity dot never overlaps the label, and both label lines use the selected-row foreground.

Final rendering result:

12 executed
12 passed
0 failed

Neighboring rail behavior

The following suites cover the unchanged workspace model and neighboring behavior:

  • WorkspaceRailStoreTests
  • WorkspaceRailOrderingTests
  • WorkspaceRailMetricsTests
  • WorkspaceRailScrollGeometryTests

Result:

137 executed
137 passed
0 failed

Build, documentation, and lint

After rebasing onto the latest main and regenerating the Xcode project:

verify.sh generate: PASS
verify.sh build: PASS
verify.sh docs: PASS
swiftlint lint --strict: 0 violations
git diff --check: PASS

verify.sh lint still reports two pre-existing agent-document references outside this change: CLAUDE.md references the missing AXCell symbol, and verification.md references the unavailable /Applications/Xcode-beta.app. The changed Swift files themselves have zero lint violations.

Review

A fresh independent review initially raised concerns about selected-row attributed-text contrast and arbitrary ultra-long near-duplicate names.

The selected-row concern was tested against the actual product cell. Both label lines render with the selected-row foreground, and a pixel-level regression test now pins that behavior.

The ultra-long near-duplicate case remains a fixed-width truncation limitation equivalent to exact duplicate user-assigned connection names. The full connection, host, and container remain available in the tooltip, and the reported production/staging class of issue is covered by the product-cell raster test.

After reviewing the corrected matcher and selected-row raster evidence, the final verdict was:

SHIP

Not verified

No full TableProUITests flow was added. The current isolated UI fixture opens one sample SQLite connection, while the connections strip appears only after a second workspace exists. A new UI test would otherwise depend on the user connection store or a live database, neither of which is deterministic or safe.

The following remain manual proof layers:

  • a running app window with two isolated workspace fixtures
  • VoiceOver speech in the full app
  • Accessibility Inspector inspection of the complete window tree
  • sanitized full-window light and dark screenshots

The deterministic behavior changed by this PR is covered through AppKit cell configuration, layout, raster, semantic-label, keyboard matcher, neighboring workspace-model tests, and a Debug build.

@devy1540 devy1540 changed the title feat(sidebar): 연결 스트립 작업공간 식별성 개선 feat(sidebar): show connection identity in connections strip entries Aug 28, 2026
@devy1540
devy1540 force-pushed the feat/workspace-identification branch from ea07d2c to 406870b Compare August 28, 2026 01:13
@devy1540
devy1540 marked this pull request as ready for review August 28, 2026 01:14

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 406870b038

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +65 to +66
matchesPrefix(entry.connection.name, search: search)
|| matchesPrefix(entry.container, search: search)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Normalize names before type-select matching

When a pasted or imported connection name contains a leading line separator, the cell flattens that separator to a space, but type-select compares against the unmodified value. Such names are accepted because connection validation trims only .whitespaces, so a displayed name such as " Production" cannot be found by typing its visible alphabetic prefix production. Match the same single-line representation used by the cell.

Useful? React with 👍 / 👎.

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.

feat(sidebar): improve workspace identification in the connections strip

1 participant