Commit Graph
22 Commits
Author SHA1 Message Date
yonlu c530dc6cb8 feat: local-first data pipeline — check library before API calls
Audit of all external calls across explore components, with local
sources checked first:

1. loadThumbnails: seeds thumbnailCache from library album cover
   art (CoverArtMedium/Small by MBID) before building the API
   request list. Library albums show cover art instantly; only
   non-library albums hit the GetThumbnails API.

2. loadArtistImages: seeds artistImageCache from library store
   (ImageMedium/Small by MBID) before the sequential API loop.
   Library artists show images instantly; only non-library artists
   hit GetArtistImageURL.

3. checkLibrary (explore-view): checks library store MBIDs
   frontend-side for artists and albums. Only falls back to
   CheckLibraryMBIDs API for recordings (not in library store).

4. checkLibrary (artist-details): same frontend-first approach
   using library album MBIDs.

5. hydrateFromCache (artist-details): now also checks library
   store directly for artist images when explore cache is empty
   (handles direct navigation without prior search).
2026-03-30 16:18:22 -04:00
yonlu 408d2ff498 feat: live toggle — views re-render when Library Only mode changes
All three explore components now subscribe to exploreSettings:

- explore-view: re-runs the current search when toggled. In
  library-only mode this means instant local-only results; toggling
  off fires the full MB/LB pipeline.

- explore-artist-details: re-runs loadAllData which branches on
  libraryOnly — switching modes live-swaps between the full API
  view and the library-only view.

- explore-album-details: re-renders to pick up any mode-dependent
  display changes.

All subscriptions are cleaned up in disconnectedCallback.
2026-03-30 15:42:58 -04:00
yonlu d73226b173 feat: Library Only mode — toggle, search, artist page, similar artists
Backend:
- Migration 17: similar_artist_map table stores per-artist similar
  artist relationships (source_mbid → similar_mbid + name + score)
- Tier 4 index build now persists similar artists to this table
- GetLibrarySimilarArtists(mbid) queries similar artists filtered
  by JOIN with the artists table (library-only, no API calls)
- Added db field to explore.Service for direct queries

Frontend:
- ExploreSettingsStore with libraryOnly toggle, persisted to
  localStorage
- Top bar toggle button with active/inactive styling
- Explore search: skips full MB/LB pipeline when library-only,
  uses only searchLibraryCache (pure JS, instant)
- Artist detail page: in library-only mode, skips all API calls
  (no top tracks, no top releases, no LB play count, no MB
  artist lookup). Uses library store for discography, calls
  GetLibrarySimilarArtists for similar artists.
- Similar artists section: changed from horizontal scroll to
  wrapping flex layout with collapsible toggle (Show all N)
- Removed debug artist ranking log
2026-03-30 15:36:37 -04:00
yonlu 5744679a80 feat: collapsible discography groups — 1 row by default, expand to see all
Each release type group (Albums, EPs, Singles, etc) now shows only
the first row of items (~5 albums) by default. If there are more,
a 'Show all N' toggle appears below. Clicking it expands to show
every release in the group. 'Show less' collapses back to 1 row.

Each group tracks its expanded state independently via a Set of
type names. The toggle uses the same visual style as the top
section's 'Show more' button.
2026-03-30 11:41:19 -04:00
yonlu a2cb72c0f1 feat: show total LB play count on artist detail page
Added GetArtistPlayCount(mbid) — fetches ArtistPopularity from LB
for a single MBID and returns the total listen count. Fire-and-forget
call on the artist page, displays below the meta line as
'1.3M plays on ListenBrainz' (uses existing formatListenCount).
2026-03-30 08:29:58 -04:00
yonlu c7b859507d fix: detail view layout — gap at top and scroll cutoff at bottom
Three changes:

1. Added box-sizing: border-box to :host of explore-artist-details,
   explore-album-details, and artist-details. The light DOM rule
   .main-panel > * sets this but shadow DOM may not inherit it.

2. Changed .main-panel to display: flex; flex-direction: column.
   In block layout, a height:0 hidden view could affect the
   position of the detail view below it. In flex column layout,
   the hidden view (flex:0) collapses completely and the active
   view (flex:1) fills the remaining space.

3. Changed .main-panel > * from height:100% to flex:1; min-height:0.
   In a flex column, flex:1 correctly fills available space while
   min-height:0 allows the content to shrink below its intrinsic
   size (needed for overflow:hidden to work).
2026-03-30 03:56:13 -04:00
yonlu 078db73e75 feat: show release year instead of type on top release cards
Added date field to LBTopReleaseGroup from the LB API's
release_group.date. Card now displays the 4-digit year
extracted via extractYear() instead of the release type.
2026-03-30 00:20:20 -04:00
yonlu 1f9b3452fa fix: show 2 top releases by default, 4 when expanded 2026-03-30 00:10:26 -04:00
yonlu 7addee575a fix: top releases grid always 2×2, fills available column height
Changed from auto-fill (which created a single row of 4) to fixed
2-column grid. Column is now a flex container so the grid stretches
to fill the section height alongside the track list.
2026-03-30 00:01:13 -04:00
yonlu 92cd6f268c feat: wire detail pages to explore cache for instant hydration
Artist detail page:
- Checks exploreCache for pre-loaded artist image (from search)
- Checks libraryStore for albums by this artist (by name match)
  and shows them as discography instantly before API calls
- Skips fetchArtistImage if cache already provided one

Album detail page:
- Checks exploreCache for cached album metadata (title, artist,
  year) from search results and pre-populates the header
- API calls still run to get full data (releases, tracks)
2026-03-29 19:03:30 -04:00
yonlu 50df4676f8 fix: artist flash on search + independent top section columns
Three fixes:

1. SearchLocal no longer applies minBlendedScore filter — index hits
   use scalePopularity scores that aren't comparable to blended
   MB+LB scores. This prevents artists from appearing in local
   results then disappearing when the full pipeline replaces them
   with score-filtered results.

2. Top section columns now render independently — tracks show as
   soon as they load, top releases show their own loading state or
   appear when ready. Previously the entire section was blocked
   until both finished loading.

3. Top releases column shows a loading spinner while its data is
   still fetching, rather than being invisible.
2026-03-29 17:23:13 -04:00
yonlu cef6709d9a feat: top releases sorted by popularity with library-style album cards
Replaced the date-sorted release group approach with a dedicated
TopReleaseGroupsForArtist LB API call that returns releases ranked
by total listen count (popularity). Added LBTopReleaseGroup type
and Wails bindings.

Restyled the top-releases cards to match the library album view:
square cover art on top with title and type below, centered text,
auto-filling the available width with even spacing.
2026-03-29 17:12:30 -04:00
yonlu fb3a340fa2 fix: compact top-releases cards to match track list height
Replace full album cards (square art + text below) with compact
horizontal cards: 44px art thumbnail on left, title + year on right.
Cards fit ~56px tall each, so a 2×2 grid of 4 releases aligns with
the height of 5 track rows in the left column.
2026-03-29 16:26:02 -04:00
yonlu a312c3d2cf feat: two-column top section — tracks + releases side-by-side
Replace full-width top tracks with a split layout: top tracks on the
left (5 default), top releases grid on the right (2×2 = 4 default).
A 'Show more' toggle below both columns expands to 10 tracks and 8
releases. Top releases are sorted newest-first from the existing
discography data.

The full discography section remains below for browsing by type.
2026-03-29 16:21:01 -04:00
yonlu 4e9df89f93 feat: add artist images to similar artists section
After similar artists load, fetch images for each via GetArtistImageURL
in parallel. Images pop in as they resolve — letter avatars remain as
fallback for artists without images. Each image is cached on disk after
first resolution, so subsequent views are instant.
2026-03-29 15:53:45 -04:00
yonlu 1797eef844 feat: 'In Library' badges on explore artist detail page
Add CheckLibraryMBIDs call after artist data loads. Checks all
release group MBIDs from the discography against the local library.
Matching albums show a green 'In Library' badge in the album meta
section alongside the year.

Fires after Promise.allSettled completes (same timing as artist
image fetch). Non-blocking — badge appears on re-render when the
check completes.
2026-03-26 12:10:26 -04:00
yonlu 55473dd52a feat: artist images from MusicBrainz/Wikidata/Wikimedia Commons
Add ArtistImageProvider that resolves artist MBIDs to photo URLs:
1. MB url-rels 'image' type → extract Commons filename → thumb URL
2. MB url-rels 'wikidata' type → Wikidata P18 property → thumb URL
3. No image → falls back to initial-letter avatar

Wikimedia Commons thumb URLs constructed via MD5 hash bucketing
(standard Commons URL scheme). Results cached in explore_cache
with 30-day TTL — subsequent lookups are instant.

Frontend: search results and artist detail page show artist photos
in the circular avatar when available. Images load async and
replace the initial-letter fallback on arrival. Artist detail page
fires the image fetch alongside the other 4 parallel data loads.

Architecture supports adding more sources (fanart.tv, etc.) by
extending the resolve() method's source chain.
2026-03-25 19:55:10 -04:00
yonlu f2a703ed52 feat: show English alias for non-Latin script artists
Extract primary English alias from MusicBrainz artist data when the
canonical name uses non-Latin script (CJK, Cyrillic, etc.). Display
it as the primary name in search results and artist detail header,
with the native script name as a subtitle beneath.

Example: 山下達郎 now shows 'Tatsuro Yamashita' prominently with
'山下達郎' as a subtitle. Artists with Latin names are unchanged.
2026-03-24 22:47:39 -04:00
yonlu 4ddd252e1e fix: don't double-pluralize Albums/Other Albums section headers 2026-03-24 21:43:35 -04:00
yonlu 450f6002a2 feat: split artist discography into Albums vs Other Albums
Use MusicBrainz secondaryTypes to distinguish studio albums from
compilations, soundtracks, live albums, remixes, etc. Albums with
no non-studio secondary types show under 'Albums'; everything else
under 'Other Albums'. EPs and Singles remain their own sections.

Section order: Albums → EP → Single → Other Albums → ...rest.
2026-03-24 21:40:25 -04:00
yonlu bb271e86f5 feat(S03/T02): Add similar artists horizontal scroll section with click…
- frontend/src/components/explore-artist-details/explore-artist-details.ts
2026-03-24 13:43:22 -04:00
yonlu 6ee16c7a87 feat(S03/T01): Add explore-artist-details Lit component with artist hea…
- frontend/src/components/explore-artist-details/explore-artist-details.ts
- frontend/index.ts
2026-03-23 23:33:27 -04:00