Skip to content

library: spinner loader + hide native search clear button#144

Merged
MaryWylde merged 39 commits into
devfrom
fix/library-ui
Jun 16, 2026
Merged

library: spinner loader + hide native search clear button#144
MaryWylde merged 39 commits into
devfrom
fix/library-ui

Conversation

@MaryWylde

Copy link
Copy Markdown
Contributor
  • Replace the plain "Loading…" text with the library Loader spinner, centered in the content area
  • Hide WebKit's native search-cancel button so it no longer doubles up with the custom clear icon

MaryWylde and others added 30 commits May 8, 2026 15:16
Chore: New Article type - AI
hotfix: remove unauthenticated test-login endpoint
fix(ui): dark-theme polish for mobile biases + center mobile Box
Feat:  Add custom Analytics
Chore: Change dark theme image of Used By section
…ct-src

Production CSP shipped with the 2026-05-26 deploy allow-listed only the
primary GA/Mixpanel hostnames, but GA4 actually POSTs to region-prefixed
shards (region1.analytics.google.com, ...), Google Ads conversion uses
stats.g.doubleclick.net, and Mixpanel's JS SDK uses api-js.mixpanel.com.
Every analytics beacon was silently CSP-blocked at the browser — net
effect: GA and Mixpanel dark in prod since the deploy. Same fix already
hot-patched in the running container; this commit persists it across
rebuilds.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds https://www.google.com to connect-src and img-src so the
Google Ads conversion beacon (www.google.com/ccm/collect) is not
blocked by the site's own CSP. Verified live on prod via QA capture.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Address tech-lead review on /api/concierge-landing:
- per-IP sliding-window rate limit (30/hr) as the real budget guard;
  the bot-UA filter is bypassable and only a cost hint now (comment fixed)
- clamp title/prevQuery/prevAnswer before prompt injection to cap tokens

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The UXCoreOSS fold-in (4691c08) copied the NewUpdateModal component and
its getNewUpdate fetch but never carried over the container that mounts
it, so the Strapi-driven news modal has been dead on prod since May 14.
Add a container that fetches the new-update single-type, gates on the
"Frontend modal visibility" flag, honours "Appears after x seconds", and
mounts it on UX Core routes. Also fix the empty index.ts export and the
inaccurate props type.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
fix(uxcore): restore New Update Modal wiring dropped in May-14 fold-in
… globe

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… label

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…aude.md lines

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…kind rows

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
manager and others added 7 commits June 11, 2026 10:17
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…anko mark

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ass, localized telegram label

Add linkLabel field so the receptionist dossier shows friendly text instead
of the raw URL; give TelegramMark its own telegram-mark CSS class so it can be
styled independently of the globe; route the TELEGRAM label through STRINGS for
EN/RU locale-completeness parity.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Replace the plain "Loading…" text with the library Loader spinner, centered in the content area
- Hide WebKit's native search-cancel button so it no longer doubles up with the custom clear icon

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add client-side search that filters shelf objects by title, author, and
tag name with a smooth card-enter animation and empty-results state.
Wire up title autocomplete and autofill (books/video via Google APIs,
audio via iTunes) with server-side API routes. Make object modals
responsive with visible custom scrollbars, fix mobile toolbar/header
overlap, keep the Select-shelf button visible on private shelves, add a
mobile trigger for the right info panel, gate the Tags Edit button on
having at least one tag, and derive object Source from the form URL.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@MaryWylde

Copy link
Copy Markdown
Contributor Author

@claude, review this PR.

@claude

claude Bot commented Jun 15, 2026

Copy link
Copy Markdown

Claude finished @MaryWylde's task in 3m 15s —— View job


PR Review

  • Gather context and read changed files
  • Review diff and key components
  • Post full review findings

Scope vs. Description

The PR title and body describe two small changes (spinner loader, hide WebKit cancel button — covered by commit b886517, 3 files). The second commit (10f5619) is a separate, substantially larger feature: client-side search, full autofill for books/audio/video, a new TitleAutocomplete component, four API routes, responsive/mobile polish across a dozen components, and a detectSource utility — 42 files and 1617 additions. The PR body does not mention any of this. Worth either splitting the PR or at minimum updating the description so reviewers know what they're actually looking at.


Findings

Bug / Rule Violation

1. TitleAutocomplete/index.tsx violates barrel convention

src/components/library/molecules/TitleAutocomplete/index.tsx:1–2

export * from './TitleAutocomplete';
export * from './TitleAutocomplete.types';

Project rules (keepsimple skill + AGENTS.md) require:

  • Barrel file named index.ts (not .tsx)
  • Default export only: import TitleAutocomplete from './TitleAutocomplete'; export default TitleAutocomplete;
  • Named exports in barrels are explicitly listed under "Never Do"

The AddObjectModal imports this as { TitleAutocomplete } — that named export path works, but it's inconsistent with every other component in the library. Fix this →


2. detectSource placed in the legacy utils/ directory

src/utils/library/detectSource.ts

AGENTS.md / keepsimple skill: "Put new utilities in src/lib/, not src/utils/ (legacy)."
This should live at src/lib/library/detectSource.ts. Fix this →


3. Hardcoded gendered pronoun in visitor toolbar

src/components/library/organisms/LibraryToolbar/LibraryToolbar.tsx:315

"along with an incredible playlist full of his favorite songs."

"his" is hardcoded regardless of library owner gender. Should be "their". Fix this →


Design / UX Questions

4. Search is owner-only — intentional?

LibraryToolbar.tsx:298–320 returns early with the visitor welcome banner for non-owners, so the search Input (rendered after that if (!isOwner) return) is never shown to visitors. A visitor browsing a large library can't search it. Worth confirming this is deliberate — it's an easy addition once confirmed.


5. langRestrict: 'en' silently drops non-English books

src/pages/api/library/autofill/book.ts:48–51

The comment acknowledges this is a bias toward English editions. The problem is it's silent — a user typing "Война и мир" gets zero suggestions with no explanation. The fallback to manual entry works, but a UX note or a retry without langRestrict when results are empty would help. Not a blocker, but worth tracking.


Security — Good Catches

The cover image proxy (src/pages/api/library/autofill/cover.ts) is well-hardened:

  • SSRF guard: strict allowlist against an enumerated set of CDN hostnames
  • Redirect re-check: isAllowed(upstream.url) re-validates after any redirect chain
  • Content-type guard: rejects non-image/* responses
  • Size limit: 5 MB cap consistent with the upload limit

API keys (GOOGLE_APIS_KEY, YOUTUBE_API_KEY) are server-only — no NEXT_PUBLIC_ prefix. Well done.


Minor / Nitpicks

6. as never casts in applySuggestion

AddObjectModal.tsx:213–222setValue('sourceUrl' as never, ...) extends a pre-existing workaround for RHF's discriminated-union limitation. Not new here but the new autofill code adds several more instances. A type ObjectWithUrl = VideoFormData | AudioFormData guard would eliminate them for the URL/source/duration fields.

7. No rate limiting on autofill routes

src/pages/api/library/autofill/*.ts — none of the four routes implement request rate limiting. A logged-in user could exhaust Google's quota rapidly. Acceptable for now given Google's own server-side quotas, but worth tracking as the feature usage scales.

8. detectSource fallback for unknown hosts returns SLD

src/utils/library/detectSource.ts:40–42podcasts.example.com"Example". This works for known platforms but produces surprising source values for generic/obscure URLs (e.g. a Google Drive link would set Source to "Drive"). Returning undefined for unknown hosts and leaving Source blank might be less confusing than a guessed name.


What's Well Done

  • Race condition handling in TitleAutocomplete is correct: a requestIdRef discards stale responses when a new query fires before the previous one returns.
  • suppressQueryRef prevents re-opening the suggestion menu when the input value is updated programmatically via applySuggestion — a non-obvious subtlety handled correctly.
  • fetchCoverFile is best-effort and never blocks the rest of applySuggestion from landing.
  • The resequencing animation in Library.tsx uses requestAnimationFrame to reset and then re-apply the class, correctly replaying the animation on rapid re-saves.
  • Cover proxy caching (Cache-Control: public, max-age=86400) warms the CDN and avoids redundant upstream fetches for the same thumbnail.

Summary

Three actionable items before merge: the barrel convention on TitleAutocomplete/index.tsx, the detectSource location, and the hardcoded "his" pronoun. The PR description mismatch isn't a code problem but should be updated so this doesn't land as a mystery diff in the git history. Everything security-sensitive (the cover proxy, key handling) is solid.

@MaryWylde MaryWylde merged commit d5abf9b into dev Jun 16, 2026
2 checks passed
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