Skip to content

Fix/ux round 2 - #3

Merged
Yefee8 merged 3 commits into
mainfrom
fix/ux-round-2
Aug 1, 2026
Merged

Fix/ux round 2#3
Yefee8 merged 3 commits into
mainfrom
fix/ux-round-2

Conversation

@Yefee8

@Yefee8 Yefee8 commented Aug 1, 2026

Copy link
Copy Markdown
Owner

No description provided.

Copilot AI review requested due to automatic review settings August 1, 2026 17:57
@Yefee8
Yefee8 merged commit 42b02fb into main Aug 1, 2026
1 check passed

Copilot AI 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.

Pull request overview

This PR refines UX and correctness around library/stats by (a) making “unknown” artist/album metadata consistently representable and localizable without persisting translated phantom rows, (b) extracting listen-cycle bookkeeping into a unit-tested helper to address repeat-one/restart edge cases, and (c) adding targeted performance instrumentation and defensive tab-level error boundaries.

Changes:

  • Group missing artist/album under a reserved rollup/entity id (0) and propagate “Unknown artist/album” labels through stats + library UI.
  • Introduce ListenCycle (with tests) and integrate it into AudioEngine to make listen banking/restarts testable and less stateful.
  • Reduce library row-press latency by precomputing the playable queue + id→index map; add perf timing hooks and tab error boundaries.

Reviewed changes

Copilot reviewed 45 out of 46 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/services/stats/rollups.ts Introduces UNKNOWN_ENTITY_ID and assigns null artist/album to the reserved rollup id.
src/services/stats/rollups.test.ts Updates rollup-delta expectations to cover unknown artist/album grouping.
src/services/stats/listenCycle.ts Adds a unit-testable listen lifecycle accumulator/banker.
src/services/stats/listenCycle.test.ts Tests pause/playing accumulation and repeat-one restart semantics.
src/services/scanner/trackMapping.ts Ensures enriched tag fields include nullable artist/album/albumArtist consistently.
src/services/scanner/trackMapping.test.ts Verifies missing collection tags remain null for fallback grouping.
src/services/perf/index.ts Uses a monotonic clock when available; improves measurement precision formatting.
src/services/audio/AudioEngine.ts Replaces ad-hoc listen timing with ListenCycle integration.
src/i18n/locales/tr.json Adds common strings for unknown artist/album and generic error/retry labels.
src/i18n/locales/en.json Adds common strings for unknown artist/album and generic error/retry labels.
src/features/stats/StatsScreen.tsx Passes unknown labels into stats UI components for reserved rows.
src/features/stats/components/Wrapped.tsx Displays unknown fallback text when top entries have no title.
src/features/stats/components/TopList.tsx Supports per-list unknown-title fallback for reserved rows.
src/features/playlists/components/PlaylistEntryRow.tsx Uses localized unknown artist/album fallbacks in subtitles.
src/features/playlists/components/AddTracksSheet.tsx Memoizes pick rows; removes inline handlers; uses unknown fallbacks.
src/features/player/PlayerScreen.tsx Switches to common unknown-artist i18n key.
src/features/player/components/QueueRow.tsx Uses localized unknown artist/album fallbacks in subtitles.
src/features/player/components/MiniPlayer.tsx Adds perf measure hook; tweaks pan activation; adds Android ripples; shows unknown artist.
src/features/library/LibraryTracks.tsx Precomputes playable queue + id→index map; adds perf marks/measures for row press.
src/features/library/LibraryScreen.tsx Fixes displayed count for artist/album views; threads kind to grids.
src/features/library/components/TrackRow.tsx Uses unknown fallbacks and adds Android ripple.
src/features/library/components/TrackInfoSheet.tsx Displays localized unknown artist/album rather than a dash for nulls.
src/features/library/components/TrackActionSheet.tsx Shows localized unknown artist/album in sheet subtitle.
src/features/library/components/LibraryHeader.tsx Adds Android ripple feedback to header actions.
src/features/library/components/CollectionHeader.tsx Renders unknown artist/album titles/subtitles based on flags; stabilizes recyclingKey.
src/features/library/components/CollectionGrid.tsx Threads kind so cards can label unknown rows correctly.
src/features/library/components/CollectionCard.tsx Renders localized unknown names/subtitles; adds Android ripple; updates memo comparator.
src/features/library/CollectionDetailScreen.tsx Passes unknown flags through to the collection header.
src/db/seed.ts Clears dependent tables transactionally so seeded tracks can be removed safely.
src/db/queries/tracks.ts Groups null artist/album into id 0 cards; supports browsing unknown collections via isNull.
src/db/queries/stats.ts Left-joins artists/albums so reserved entityId=0 (and missing refs) can render with fallbacks.
src/components/ui/TabErrorBoundary.tsx Adds a tab-scoped error boundary with retry UI.
src/components/ui/SegmentedControl.tsx Adds Android ripple feedback for segmented options.
docs/stats.md Documents reserved rollup id 0 and left-join rendering strategy.
docs/scanner.md Documents how ARTIST/ALBUM/ALBUMARTIST resolve normalized foreign keys.
docs/performance.md Documents measured row-press latency improvements and updated test counts.
docs/components.md Documents TabErrorBoundary and updates MiniPlayer behavior notes.
docs/adr/013-unknown-metadata.md Adds ADR describing “unknown metadata stays null” + reserved rollup id approach.
docs/adr/012-artist-and-album-shelves.md Updates ADR to reflect track-first grouping and unknown-card behavior.
app/(tabs)/stats.tsx Wraps stats tab route with TabErrorBoundary.
app/(tabs)/settings.tsx Wraps settings tab route with TabErrorBoundary.
app/(tabs)/playlists.tsx Wraps playlists tab route with TabErrorBoundary.
app/(tabs)/index.tsx Wraps library tab route with TabErrorBoundary.
app/(tabs)/_layout.tsx Adds perf timing hooks for tab press→focus.
.gitattributes Marks a historical diff-repair path as reviewable.
Suppressed comments (1)

src/services/audio/AudioEngine.ts:438

  • repeat === 'one' can finish a track without calling loadIndex (it seeks to 0). In that path didJustFinish closes the listen via flushListen(true) but never opens the next cycle, so subsequent loops won’t be banked (the regression described in ListenCycle). Open the next cycle when didJustFinish fires in repeat-one mode.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +16 to +18
/** Keeps a render failure inside one tab instead of taking down the whole app. */
// React render error boundaries require a class component.
export class TabErrorBoundary extends Component<TabErrorBoundaryProps, TabErrorBoundaryState> {
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