Release 1.8.0 - #2398
Open
catch-21 wants to merge 39 commits into
Open
Conversation
* fix: stream pagination livelock on long filtered runs * refactor: keep sentinel mounted until exhausted * fix: broken tests after merge with dev * refactor: small cleanups
* docs(adr): align application orchestration rules with runtime * docs(adr): clarify application orchestration constraints
…2339) * feat: add JSON-LD for AI agents and crawlers to learn of Nexus-Scout * fix: update comments inline with review feedback
'My network' (wot) and 'Tagged as' (wot_domain) streams never contain the viewer's own posts: Nexus excludes them server-side and the local create path never writes into those streams, so the optimistic entry flashed at the top and vanished on the next stream reset. Closes: #2308
* fix(ui): expand truncated post text in place Clicking Show more now reveals the rest of the post on the feed instead of navigating to the post page. Closes: #764 Co-authored-by: Orlando Goncalves <orlando.goncalves@gmail.com> * test(ui): update Show more snapshots after expand-in-place Closes: #764 --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
* feat(users): add safe moderation bot default follow Apply the configured moderation follow once during shared bootstrap while preserving explicit unfollows with a durable homeserver marker. Treat expected homeserver misses as ordinary existence results and keep production moderation disabled when no identity is configured. Fixes: #2255 * fix(config): update staging moderation bot id * test(config): align moderation id with runtime default * fix(users): harden moderation follow migration Preserve moderation opt-outs before unfollowing and cancel detached follow work across authentication lifecycles. Use identity-safe specs builders, SDK existence probes, and visible deployed configuration warnings. Refs: #2255 --------- Co-authored-by: V <jovanovicv90@gmail.com>
#2285 stretched the trigger across the header row, so hovering empty space next to the timestamp opened the profile card again.
* fix(ui): match profile empty states to Figma Notifications, Posts, and Replies used generic or outdated placeholders on empty profile tabs. Closes: #1789 * fix(ui): use correct profile empty-state artwork
* feat(auth): block prod-key sign-in on staging homeserver deploys
Reject mnemonic, encrypted-file, Pubky Ring, and session-restore auth
when the key's PKARR homeserver does not match a staging deploy:
- Declare deploy identity via a required PUBKY_RUNTIME_ENV
("production" | "staging") runtime value and drive
isStagingHomeserverDeploy() from it, so config drift can never
silently disable the guard. PR previews, the CI smoke test, and local
dev declare theirs in-repo; deployed configs fail loudly at boot when
it is missing.
- Fail closed on staging: a mismatched, absent, or unresolvable PKARR
record blocks sign-in and never republishes the record. Outside
staging, the sign-in self-heal republishes only a provably absent
record - a failed lookup now propagates instead of force-overwriting
a record that may point at another homeserver.
- Enforce the same check when restoring a persisted session: transient
lookup failures retry like any other restore failure, and definitive
mismatches clean up local state, surface a wrong-environment toast,
and sign the rejected session out of its own homeserver (also on the
Ring path) instead of leaving it dangling.
- Show the rejection toast across both restore dialogs and the Ring QR
flow (expiring the stale auth URL), localized in all nine locales.
Closes #2126
* fix(auth): single environment assert per flow, quieter guard rejections
Address review findings on the staging sign-in guard:
- Run the environment guard once per flow: keypair sign-ins rely on the
assert inside HomeserverService.signIn (before the session exists), while
initializeAuthenticatedSession keeps it as the sole checkpoint for
externally approved (Ring) sessions and now signs the session out on any
guard failure, not only wrong-environment rejections.
- Reject an absent PKARR record on staging as WRONG_ENVIRONMENT_HOMESERVER:
absence is deterministic and cannot prove the key belongs to this deploy,
so it no longer surfaces as a retryable server error (10x3s retry storm)
or a misleading file-error message in the restore dialogs.
- Construct the wrong-environment rejection directly instead of via the Err
factory: an expected user mistake no longer emits an error log plus a
Sentry error event on every attempt (Logger.info with context instead).
- Keep the restored session across restore retries so a transient PKARR
lookup failure retries only the environment check, not the whole
restoreSession round-trip; collapse the nested wrong-env classification
into the single retry catch.
- Log persisted-session restore failures swallowed by logout() instead of
silently returning.
- Merge useAuthUrl's duplicated catch branches into one toast with a
conditional description.
- Remove the signIn store's dead error field and setError action (last
caller was replaced by reset()).
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
) * feat(ui): simplify and optimize collection cards mobile rendering * fix(ui): block collection follow while state loads * fix(ui): keep collection tag action last * fix(ui): address collection card review feedback * test(vrt): regenerate baselines 2026-08-19T19:19:14Z --------- Co-authored-by: V <jovanovicv90@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat(ui): group repeated deleted and edited post notifications Consecutive delete/edit notifications from one actor collapse into a single row per content kind: deleted groups render as a flat unlinked total, while edited groups list every affected post behind a Show/Hide disclosure on desktop and render permanently expanded on mobile. Repeats about the same post deduplicate to their newest occurrence. Edited posts refetch on notification arrival so rows never show pre-edit content, poll refreshes merge new notifications in place instead of remounting the list, load failures keep the accumulated rows with an inline retry, and auto-loading budgets pages that grouping leaves without new rows, handing control back through a manual Load more button. Single deleted rows drop their post link — the deleted post has no destination. Shared row chrome (avatar, heading, timestamp and icon) is extracted for both row kinds, and notification previews derive through the app-wide preview policy. * test(e2e): cover grouped notifications in the cypress spec The two '…that you reposted' scenarios now create two posts each, so they form a grouped row on their own and assert the grouped copy. The edited scenario drives the Show/Hide disclosure on desktop and asserts the permanently expanded title list on the mobile config. * fix(notifications): harden refresh, disclosure state and mobile snapshot Refresh now stands in for a failed initial load by establishing the pagination cursor, so retrying no longer leaves the list stuck on its first page, and a refreshed page that filters down to nothing (every actor muted) no longer looks like a gap and wipes the loaded rows. Group disclosure state moves to the list, keyed by the run's members rather than by row identity: a run gains members as pages load and refreshes arrive, which changes the row key, and the group the user is reading no longer collapses when that happens. Also mirror the desktop render in the mobile snapshot and apply the documented viewport helpers, take the module-level toast in the post content hook, and use relative imports between same-tier siblings. * test: drop the obsolete notifications list snapshot The mobile snapshot was renamed when it started mirroring the desktop render; its old entry stayed behind and CI fails on obsolete snapshots.
* fix(ui): add bottom padding so profile links clear mobile footer * Remove desktop spacing. Update tests. --------- Co-authored-by: Taehwa Kim <hadeath03@gmail.com>
Moving the cursor over a hover popover trigger (post header name, mention link, feed row avatar) blurred whatever element was focused, killing tag input focus mid-typing (#2291). Two causes: - handleMouseLeave unconditionally blurred document.activeElement whenever the cursor left a hover trigger, even if the popover never opened. Removed. - Radix non-modal popovers focus the trigger on close, stealing focus from the input when a hover popover with a focusable trigger closes. PopoverContent now prevents open/close auto-focus in hover mode only; click-mode popovers keep Radix's default a11y focus behavior. Co-authored-by: Taehwa Kim <hadeath03@gmail.com>
* test: 3 new WoT feed E2E * tests: fix other e2e * tests: refactor feed tests (WoT) * tests: refactor cypress slow down in feed e2e * tests: e2e workflow pubky-homeserver * tests: revert check for moderation follow, now disabled in testnet
* feat(ui): show status emojis inline with user names * fix(ui): preserve text-only profile statuses * fix(ui): restore profile header typography spacing
…load (#2295) * fix(core): refresh follow-dependent feeds Invalidate dynamic follow-dependent caches after follow mutations and force-refresh mounted feeds from Nexus using revision signals. Refs: #2294 * fix(core): harden follow-driven stream refreshes Serialize same-stream cache work, add the refreshStreamSlice contract, and prevent stale pagination requests from overwriting follow-driven refreshes. Preserve optimistic posts and existing pagination when the automatic refresh fails. Refs: #2294 * fix(core): keep feeds visible during follow refresh Preserve rendered posts while follow-driven replacement loads and tighten serializer ownership and stream-switch regression coverage. Refs: #2294 * revert(core): drop mounted-feed force refresh after follow mutations Team decision (PR #2295 review + Slack): a follow/unfollow must not live-refresh the feed the user is reading. Remove the streamInvalidation store, useFollowDependentStreamRefresh, refreshStreamSlice and the pagination concurrency machinery that existed only to make the in-place replacement safe. Keep the additive follow-dependency classifier, stream id fixtures and grammar tests as groundwork for deferred invalidation. Refs: #2294 * feat(streams): defer follow and profile-tag feed invalidation to next load Mutations now only mark dependency scopes dirty in an in-memory registry (follow_graph on any follow mutation, friends on friendship transitions, profile_tag on profile-tag writes). Each dependent stream drops its main and unread cache rows lazily in prepareStreamForInitialLoad, so a mounted feed keeps its membership and scroll position while navigation back or pull-to-refresh rebuilds it from Nexus. wot_domain streams reconcile on profile-tag changes at every depth and on graph changes at depths 1-2. The activeStreamId store lookup is removed end to end: preserving the mounted row is now the default behavior, not a carve-out. Refs: #2294, #2302 --------- Co-authored-by: secondl1ght <85003930+secondl1ght@users.noreply.github.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com>
* fix(ui): add paste button to collection add-post URL field The v25 Add Post dialog showed a clipboard control on Paste post url; keyboard paste already worked, but the visible control was missing. Closes: #2103 * fix(ui): harden paste-button flow and make input icon actions accessible - guard submit with synchronous refs so double-clicks cannot start concurrent pipelines, and never commit after the dialog closes - keep a slow clipboard read from clobbering text typed while waiting, and cap pasted values before they enter form state - scope the clipboard catch to the read, log it, and explain how to unblock a denied clipboard permission (sticky in Chromium) - render clickable input icons as real buttons (keyboard/screen-reader reachable, focus preserved while pending, errors announced via aria-describedby/role=alert) and use that path for the Paste button - extract readFromClipboard() beside copyToClipboard, collapse the duplicated icon slots, and restore clipboard stubs after tests --------- Co-authored-by: V <jovanovicv90@gmail.com>
* fix(ui): restore collection add-post options Restore the original responsive four-card dialog and route the new Select action to the current user's profile posts without mutating collection contents. Refs: #2105 * fix(ui): restore add-post dialog scrolling Keep the shared DialogContent vertical overflow behavior so every stacked mobile option remains reachable in short viewports. Refs: #2105
Contributor
🚀 Preview DeploymentURL: https://pubky-app-pr-2398-fzxmjul7ya-oa.a.run.app
|
* feat: attachment edit support for posts and articles * perf: load images faster * docs: update * fix(files): settle all uploads before failing commitCreate * refactor: pr comments * tests: edit and remove post image e2e * refactor: extract kind helper --------- Co-authored-by: James Browning <jamesbrowning91@gmail.com>
* tests: own profile vrt * test(vrt): regenerate baselines 2026-08-24T18:31:17Z * test(vrt): regenerate baselines 2026-08-24T18:31:19Z * tests: vrt own profile status * test(vrt): regenerate baselines 2026-08-24T19:13:57Z * test(vrt): regenerate baselines 2026-08-24T19:13:58Z * tests: 'Other profile' vrt and orphon screenshot check * test(vrt): regenerate baselines 2026-08-24T19:55:09Z * tests: vrt profile thread replies * test(vrt): regenerate baselines 2026-08-24T20:46:50Z --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* fix(posts): render more link inline with truncated text * fix(posts): preserve expansion for truncated code blocks * fix(posts): keep more control when truncation sentinel is missing Co-authored-by: Cursor <cursoragent@cursor.com> * fix(posts): anchor the inline more button to the truncated block The show-more plugin searched the whole tree for the truncation ellipsis and attached the button to the last node ending with it. Because truncatePostPreviewText always appends the ellipsis to the very end of the preview text, the cut is by definition the last top-level block, so the search could only ever go wrong: - a user-authored "..." + NBSP (as copied out of another truncated preview) took the button, leaving the real cut unmarked - the same match inside a code block stripped four characters off the user's own code - a cut landing in a blockquote or list rendered the post-level control inside the quote or bullet, styled as part of the quoted text - the no-match fallback appended a second ellipsis where the original was still visible, so tables and raw HTML showed "..." twice Attach to the last block instead, appending the ellipsis paragraph after blocks that cannot host the button and clearing their own trailing ellipsis first. Gate the button renderer on data-type="show-more" so only the plugin's own node triggers expansion, matching the hashtag and mention convention already used for links. --------- Co-authored-by: V <jovanovicv90@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(posts): compact URLs in post and article content * fix(posts): derive the compact URL from the parsed link The compact label was sliced out of the text the author typed rather than taken from the parsed destination, so the two could disagree. A post containing https://аpple.com (Cyrillic а) rendered as a clean apple.com chip while the browser resolved xn--pple-43d.com, and feed posts have no link confirmation dialog to catch it. Host extraction now lives in getUrlHostLabel beside getLabelFromUrl in @/libs/utils/urlToIcon and reads URL.host, which also normalises casing, drops a default port, and keeps www. when removing it would leave a bare public suffix (www.com -> com). The tooltip and the accessible name now render the parsed href with any credentials stripped, so a password embedded in a URL is no longer read out or left in the DOM, and a www. autolink reveals the http:// scheme its visible text omits. Remove the hand-rolled long-press gesture: four refs, five pointer handlers, the cleanup effect and the controlled tooltip state. It left a suppression flag set after a scroll, which swallowed the next keyboard activation, and it blocked the context menu after any tap, taking Copy Link away on mobile with nothing in its place. The browser's own long-press menu now fills that role, and the tooltip is hidden on coarse pointers where it would otherwise flash open on every tap. Preview truncation no longer cuts through a URL. A chopped URL still autolinks and still compacts, so it rendered as a tidy host pointing at an address that does not resolve. Where keeping a trailing URL whole hides nothing, no "Show more" is offered. The e2e spec looked posts up by text containing the full URL; it now uses a marker that renders verbatim and asserts the host label with the full destination kept on the anchor. --------- Co-authored-by: infin1t3 <jovanovicv90@gmail.com>
catch-21
force-pushed
the
release-1.8.0
branch
from
August 25, 2026 10:24
4aa7f62 to
a22fb53
Compare
catch-21
force-pushed
the
release-1.8.0
branch
from
August 25, 2026 14:14
a22fb53 to
c400558
Compare
* tests: vrt settings * test(vrt): regenerate baselines 2026-08-24T21:33:16Z * test(vrt): regenerate baselines 2026-08-24T21:33:17Z --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* tests: single post vrt * test(vrt): regenerate baselines 2026-08-25T20:19:56Z --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…2355) * feat(search): add collections section to search results (#1841) * test(vrt): regenerate baselines 2026-08-16T20:55:03Z * fix(search): keep pagination path when collections slice settles empty * feat(search): add people section to search results * test(vrt): regenerate search baselines after dev merge * test(vrt): regenerate baselines 2026-08-21T07:10:32Z * fix(search): link entire people card to profile and trim dead code --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: secondl1ght <85003930+secondl1ght@users.noreply.github.com>
* fix(ui): reveal custom feed tab pencil on hover Show a muted pencil on the right of editable feed tabs so users can open Edit without navigating. Clicking the name still opens the feed. Refs: #1898 Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ui): make custom feed tab link fill the tab Keep name clicks and empty tab space navigating to the feed while the pencil stays a separate edit control. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ui): stretch custom feed link across the whole tab h-full does not fill a min-height flex wrapper, so clicks on the tab padding still missed the link. Pin the link to inset-0 instead. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(ui): redesign feed tabs with reach label, icons, and mobile tab bar - Feed navigation is now a tab bar on mobile too (v26): the selected tab shows icon + label, other tabs collapse to icon-only, Create is a plus icon; the strip sticks under the compact mobile header (Hot pattern) and the mobile right drawer falls back to Who to follow / Hot tags. - The first tab mirrors the selected reach (My network, All, Tagged as, ...) with the matching icon, via a shared REACH_FILTER_META map. - Custom feeds get a selectable Lucide icon (icon picker dialog, dynamic icon atom, spec 0.7.0 with the icon field synced to the homeserver), ported from PR #2284 and de-i18n-ized; feeds without an icon fall back to Activity. - CustomFeedDialog moves to a useCustomFeedForm hook (react-hook-form + zod); edit/delete only navigate away when you are viewing the edited feed, and config edits use replace since the old hash id is dead. - Pencil affordance: hover-revealed on desktop, always visible on the selected custom feed tab on mobile, with a larger hit area. * fix(ui): apply code-review findings to feed tabs and icon stack - Pencil: on hover-capable lg+ pointers it hides (and ignores events) until hover/focus-within; hover-less devices (iPad, touch laptops) keep it visible since :hover can never fire there. - Feed tab bar: sticky chrome and the gradient fade move to a non-scrolling wrapper so the fade paints below the bar instead of being clipped into the scrollport with phantom vertical scroll. - Icon picker: search also matches deprecated Lucide aliases mapped to their canonical glyph (querying 'home' finds 'house'); the aliases file now stores the alias->canonical map. - Lucide catalog (~116KB dynamic-import map) is lazily chunked instead of shipping in the /home bundle; name checks are shape-based and the loader validates against the real catalog. - One controlled edit CustomFeedDialog per strip instead of a mounted react-hook-form instance per feed tab; dialog supports controlled open/onOpenChange without a trigger. - useCustomFeedForm guards submit/delete re-entrancy with a ref so a queued second click cannot start a second commit. - Shared useSelectedReachFilter hook replaces the copied reach derivation in HomeFeedSidebar and FeedNavigation; the tab falls back to All for an out-of-enum persisted reach instead of crashing. - CustomFeedDialog derives reach options from REACH_FILTER_META; tab width/padding constants unified (active pill pads px-8 everywhere). - Cleanups: sanitizeIcon at the FeedNormalizer chokepoint, stale JSDoc and duplicate import removed in feed.validators, dead HomeFeedRightDrawerMobile removed. * test(vrt): regenerate baselines 2026-08-20T09:21:51Z * refactor(ui): rework dynamic icon store and icon picker internals - Icon state moves into a subscribable module store read through useSyncExternalStore: no impure map read during render (React Compiler-safe), hydration correct by construction, one shared state per icon, and a failed chunk heals every mounted instance when any retry succeeds. Unknown names are answered from the resident catalog instead of stored, so peer-synced garbage cannot grow memory, and 'unknown' is distinguished from 'error'. - Loaded dynamic icons carry the same lucide-<name> class as static imports so CSS rules and test selectors match both. - Icon picker drops the hand-rolled scroll virtualizer (per-scroll-event renders, Tailwind-coupled constants, Tab-unreachable cells) for progressive append via the existing useInfiniteScroll hook, drops the open-animation gate that blanked the grid on every open, and defers the search query with useDeferredValue so superseded keystrokes abandon their work instead of mounting throwaway cells. - Search now also matches lucide's synonym tags ('delete' finds the trash icons) via a generated lucideIcons.tags map loaded lazily with the catalog; name matches rank first. Result count is announced via role=status. - Verified on the production build: the catalog (57KB) and tags (148KB raw) chunks stay out of the /home initial scripts. * fix(test): stabilize VRT runs against browser-mode startup races - Run VRT serialized (--no-file-parallelism): parallel page startup intermittently kills the whole run before any test executes with an unhandled 'route.fulfill: target closed' rejection from @vitest/browser-playwright (reproduced locally on two consecutive commits; serialized runs are reliably stable). Documented in docs/visual-regression-testing.md. - Pre-bundle lucide-react/dynamic.js in the vrt project so the lazy catalog import cannot trigger a mid-run dependency re-optimization and page reload under in-flight requests. - renderForVRT now waits for dynamic Lucide icons to finish loading (no empty svg.lucide in the capture root), so a baseline can never nondeterministically bake in a blank icon box; a hung chunk fails the test, matching the existing image policy. * test(vrt): regenerate baselines 2026-08-20T12:55:34Z * refactor(ui): use Container/Typography atoms and trim single-use type exports - Replace plain div/p/span in IconPickerDialog and the FeedNavigation custom-feed tab wrapper with Container/Typography (overrideDefaults), matching house style; sentinel follows the WhoToFollow precedent. - Un-export IconPickerDialogProps, DynamicLucideIconProps and LucideIconState — no external consumers. * fix(ui): ui fixes * test(vrt): regenerate baselines 2026-08-24T14:38:51Z * test(vrt): drop ineffective optimizeDeps entry, correct the parallelism note Pre-bundling lucide-react/dynamic.js does not prevent the browser-mode teardown crash — measured with and without it, parallel runs fail either way. Keep only the serialization flag, which does prevent it, and record what was actually measured. * test(vrt): run the suite in parallel again Drops the serialization flag: the browser-mode teardown race it worked around is intermittent, and a rerun is preferable to slowing every VRT run. Leaves the VRT scripts, config and docs identical to dev. * refactor(ui): move lucide helpers into libs/lucide and fix review findings - Move the lucide store, alias map, tag map and their tests from libs/utils into a dedicated libs/lucide folder. - Normalize icon-name case in one place: toLucideIconName (UI) and FeedValidators.sanitizeIcon (persistence) now agree, so an icon another client stored as 'Activity' renders its real glyph instead of silently falling back. - Cancel the VRT dynamic-icon poll on timeout so it stops burning frames for the rest of the page. - Drop the unused reset from useCustomFeedForm. - Use the shared useControlledState in IconPickerDialog instead of its own controlled/uncontrolled handling. - Close the feed edit dialog when the session ends. - Drop reach options with no home-store equivalent instead of defaulting them onto another option's label and icon. - Update the docs that referenced the old path and helper. * refactor(core): move the tagged-as reach constant out of the filter component TAGGED_AS_FILTER_KEY moves to config/feed and the ReachFilterValue type next to ReachType in the home store types, so hooks and core-adjacent code no longer import a constant from a filter component. FilterReach keeps only the presentational REACH_FILTER_META. * fix(ui): harden the icon path against peer-controlled names and load failures - Look up the Lucide catalog with Object.hasOwn: 'constructor' is an inherited key that resolves to Object, whose module has no icon node, so a synced feed carrying that name crashed the feed pages. Guard the resolved node too. - Handle a rejected catalog load in the icon picker: the loader's own catch does not cover the caller's derived promise, so a failed chunk became an unhandled rejection and left the grid loading forever. - Store lucide tags hyphenated so a multi-word query ('air conditioner') matches the 227 multi-word synonyms, not just single words. - Validate stored icons against the same name pattern the UI resolves with, now shared from config, so a name cannot be persisted and then permanently render as the fallback. - Retry icons that failed to load when the browser comes back online, which is what the component's self-healing promise claimed. - Cap the active feed tab width below lg so one long feed name truncates instead of pushing every other tab off-screen. - Drop the edit dialog's feed snapshot when a background sync removes that feed, and show a stored reach or content this dialog cannot offer as a disabled option instead of an apparently empty select. * perf(ui): load picker icons as one chunk and drop the dead mobile drawer slot - The icon picker renders ~1700 cells and lucide ships one chunk per icon, so scrolling the catalog cost ~1700 requests and ~920KB. Add a generated bundle of every canonical icon node and load it once when the picker opens: one request, ~109KB, and every cell paints straight away. Feed tabs keep the per-icon path — they render a handful of icons and must not pull the whole set. - Stop notifying subscribers when an icon enters the loading state: it renders exactly like a name that was never requested, so no output can change. Halves the notifications a picker session produces. - Skip writing an icon node that the bundle already resolved while a per-icon request was in flight. - Remove the mobile right-drawer slot from ContentLayout, the FeedSection molecule it used to hold, and the stale mock left behind: nothing has passed that slot since feed selection moved into the tab bar. - Document the three generated lucide files and when to regenerate them. --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: secondl1ght <85003930+secondl1ght@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Aldert <81586998+aldertnl@users.noreply.github.com> Co-authored-by: Taehwa Kim <hadeath03@gmail.com>
catch-21
force-pushed
the
release-1.8.0
branch
from
August 26, 2026 09:10
c400558 to
1e20fa3
Compare
* fix(ui): narrow custom feed dialog * fix(ui): narrow feed icon picker
* fix(ui): prevent profile name descender clipping * fix(ui): give profile name room for descenders via clip-margin 4px padding still clipped Inter Tight at 60px. overflow-clip-margin keeps the compact line box and paints the missing ink. Co-authored-by: Cursor <cursoragent@cursor.com> * test(ui): sync profile header snapshots with prettier class order Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: V <jovanovicv90@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Safari does not support overflow-clip-margin (through v27), so the #2422 fix only worked in Chromium/Firefox and profile name descenders stayed clipped in Safari — and the webkit VRT assertion on overflowClipMargin failed, keeping the dev VRT gate red. Swap the mechanism for bottom padding (clipping happens at the padding edge) cancelled by a matching negative margin, which every browser honors, and assert the padding pair in the VRT test instead. Co-authored-by: Cursor <cursoragent@cursor.com>
catch-21
force-pushed
the
release-1.8.0
branch
from
August 26, 2026 20:46
1e20fa3 to
a551421
Compare
catch-21
marked this pull request as ready for review
August 28, 2026 14:37
Contributor
|
Too many files changed for review (672 files, 100 file limit). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.