anyproto/anytype-ts · issue #2163 · PR #2234 · branch fix/2163-header-link-truncated-url
The URL / Email / Phone relation menu actions (Go, Copy, Reload) were reading the value to operate on from childRef.current.getValue(), which exposes whatever the child cell has chosen to render. In the featured-relations header the cell is rendered with shortUrl=true and textLimit=150, so the visible string can be a truncated form like github.com/an...issues. Even where today's text-cell implementation does not propagate the visual truncation back through getValue(), the contract left the door open: any future change could quietly surface the displayed string into the actions. The fix reads record[relation.relationKey] directly. Second PR to Anytype, opened 24h after #2233 merged.
When an object has a custom URL property pinned to the featured-relations header, the cell is rendered with shortUrl=true and textLimit=150, both come from src/ts/component/block/featured.tsx. The visible string can therefore be a truncated form like github.com/an...issues, while the underlying record value is the full https://github.com/anyproto/anytype-ts/issues. Right-click on the cell opens the URL menu with three actions: Go, Copy, Reload.
The value comes from childRef.current.getValue(). That exposes whatever the child text-cell has chosen to expose. The cell is configured to render truncated, and the data contract between the parent menu and the child renderer is implicit. Even if today's getValue() happens to return the full value, any future refactor to the text-cell render layer could quietly route the displayed string back through that ref, and the Go / Copy / Reload actions would start operating on github.com/an...issues instead of the real URL.
The record holds the authoritative URL. The child cell is a display surface. The menu actions should read from the record, full stop. Closing the implicit contract requires one line.
Why not "fix the child cell"? Because the child cell is doing the right thing: the truncation is the desired visual presentation. The bug is that the parent menu was treating the child's exposed value as the source of truth, when the record is the source of truth. The fix moves the authoritative read up to where it belongs.
src/ts/component/cell/index.tsx has no .test.ts companion. The project's vitest coverage in src/ts/lib/util/*.test.ts is utility-level; component coverage is via desktop-build manual verification. Adding a component-level test would either require introducing a new mocking surface (unprecedented in this directory) or duplicating the assertion the patch itself encodes. The convention for component patches here is: tsc + biome clean, manual verify on a desktop build. The PR body documents the manual test plan step-by-step.
Second PR to Anytype, 24h after #2233 merged. The first one was the proof. This one is the pattern. PR open against develop with GitHub-noreply identity, tsc + biome clean.
Issue #2163 was open 6 weeks, zero comments, zero PRs, but in a code area Andrew (@ra3orblade) actively maintains. The first merge (#2208) established the working relationship; this one tests whether a second pull lands as cleanly.
Traced the bug from the issue report through featured.tsx → Cell → onSelect → childRef.current.getValue(). The implicit contract between the menu and the child renderer was the surface the bug lived on, even if today's text-cell implementation happens to expose the full value. Fix tightens the contract: actions read from record[relation.relationKey], not from any child ref.
+7/-1 LOC in one file (src/ts/component/cell/index.tsx). No new TypeScript errors on the patched project. Biome lint clean. PR body documents the manual verification plan step-by-step against a desktop build.
Same noreply identity as #2233 means CLA Assistant signs automatically. Reporter (dome-mjdiaz) gets a notification with the PR link without me having to chase them via mail.
The first merge was a coincidence-rate-of-one data point. A second merge by the same maintainer in the same week converts the relationship from "I shipped a PR" to "I ship PRs here". That's the difference between a portfolio entry and a referenceable contributor relationship. If #2234 merges cleanly, the next conversation with Andrew can drop the cold-mail framing entirely.