Skip to content

feat: Minecraft Creator Playlist integration with album covers, searc… - #58

Merged
creatorcluster merged 2 commits into
creatorcluster:mainfrom
Coder-soft:main
Jul 4, 2026
Merged

feat: Minecraft Creator Playlist integration with album covers, searc…#58
creatorcluster merged 2 commits into
creatorcluster:mainfrom
Coder-soft:main

Conversation

@Coder-soft

@Coder-soft Coder-soft commented Jul 4, 2026

Copy link
Copy Markdown

…h, and changelog popup

  • Add useMinecraftMusic hook for 725 tracks from Creator-Safe Playlist API
  • Add MinecraftMusicFilter with album-based filtering, search, and cover art
  • Add 70 album cover images and albums.json track mapping
  • Add MinecraftChangelogPopup with localStorage-based one-time dismissal
  • Connect main search bar to Minecraft music track filtering
  • Add minecraft-music category to ResourceCard, types, and category utils
  • Fix AudioPlayer with allowPlayBeforeReady for pre-cached audio
  • Remove deprecated Community Assets link from Navbar/Footer
  • Filter non-MP3 files out of albumData to prevent empty 'Other' bucket

Summary by CodeRabbit

  • New Features

    • Added a new Minecraft music browsing experience with album filters, album art, search, and track counts.
    • Introduced a popup highlighting what’s new when visiting the resources page.
    • Expanded music browsing to switch between community music and Minecraft music.
  • Bug Fixes

    • Improved audio player behavior so controls can be used sooner while content is still preparing.
    • Updated navigation and footer links to better reflect the current community section.

…h, and changelog popup

- Add useMinecraftMusic hook for 725 tracks from Creator-Safe Playlist API
- Add MinecraftMusicFilter with album-based filtering, search, and cover art
- Add 70 album cover images and albums.json track mapping
- Add MinecraftChangelogPopup with localStorage-based one-time dismissal
- Connect main search bar to Minecraft music track filtering
- Add minecraft-music category to ResourceCard, types, and category utils
- Fix AudioPlayer with allowPlayBeforeReady for pre-cached audio
- Remove deprecated Community Assets link from Navbar/Footer
- Filter non-MP3 files out of albumData to prevent empty 'Other' bucket
@vercel

vercel Bot commented Jul 4, 2026

Copy link
Copy Markdown

@Coder-soft is attempting to deploy a commit to the yamura3's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Coder-soft, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7b54d4ff-89ee-4008-b8bf-e357783f3afa

📥 Commits

Reviewing files that changed from the base of the PR and between bf51f33 and e182e91.

📒 Files selected for processing (3)
  • src/components/resources/ResourceCard.tsx
  • src/hooks/useMinecraftMusic.ts
  • src/pages/ResourcesHub.tsx
📝 Walkthrough

Walkthrough

This PR adds a Minecraft-specific music mode to the Resources Hub, backed by a new album dataset and a useMinecraftMusic hook that fetches/caches a remote playlist and audio blobs. It introduces album filter and changelog popup components, extends resource category types/UI, adjusts AudioPlayer's ready-state gating, and updates navigation links.

Changes

Minecraft Music Feature

Layer / File(s) Summary
Category and type support
src/types/resources.ts, src/utils/resourceCategories.tsx, src/components/resources/ResourceCard.tsx
Adds 'minecraft-music' to the Resource.category union and to icon/color/preview switch cases, reusing music styling and preview path; also tweaks card title size.
Album dataset
public/data/albums.json
Adds a full JSON dataset mapping album names to their .mp3 track lists.
Playlist caching hook
src/hooks/useMinecraftMusic.ts
Adds useMinecraftMusic hook fetching/caching a remote playlist and albums.json map, pre-caching MP3 blobs with concurrency, computing album counts, and deriving filtered/sorted resources; exports ensurePlaylistCached.
Album filter UI
src/components/resources/MinecraftMusicFilter.tsx
Adds album search/filter component with thumbnails, selection pill, animated list, and empty-state messaging.
Changelog popup
src/components/resources/MinecraftChangelogPopup.tsx
Adds a one-time dialog announcing the Minecraft playlist integration, persisted via localStorage.
ResourcesHub integration
src/pages/ResourcesHub.tsx
Adds community/minecraft music view toggle, wires search handlers, mood-filter bypass, mobile/desktop album filter sheets, resource list source switching, and mounts the changelog popup.
AudioPlayer pre-ready playback
src/components/AudioPlayer.tsx
Adds allowPlayBeforeReady prop controlling initial loading state, loading overlay style, and control disabled logic.
Navigation link updates
src/components/Navbar.tsx, src/components/Footer.tsx
Removes "Community Assets" links and replaces the Navbar entry with a "Community" link to /community.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ResourcesHub
  participant useMinecraftMusic
  participant AlbumsJson as albums.json
  participant PlaylistAPI

  User->>ResourcesHub: opens Resources Hub / Music category
  ResourcesHub->>useMinecraftMusic: ensurePlaylistCached()
  useMinecraftMusic->>AlbumsJson: fetch album map
  useMinecraftMusic->>PlaylistAPI: fetch playlist
  PlaylistAPI-->>useMinecraftMusic: playlist data
  useMinecraftMusic->>PlaylistAPI: fetch mp3 blobs (6 workers)
  PlaylistAPI-->>useMinecraftMusic: audio blobs
  useMinecraftMusic-->>ResourcesHub: resources, albumCounts

  User->>ResourcesHub: toggle to Minecraft view
  ResourcesHub->>ResourcesHub: set musicView = minecraft
  User->>ResourcesHub: select album
  ResourcesHub->>useMinecraftMusic: setSelectedAlbum(album)
  useMinecraftMusic-->>ResourcesHub: filtered resources
  ResourcesHub-->>User: render ResourcesList with filtered tracks
Loading

Possibly related PRs

Poem

A rabbit hops through blocky lands,
With playlists cached in eager hands,
Albums sorted, thumbnails bright,
A popup pops to say "delight!"
Hop, click, and play — the tunes now flow,
🐰🎵 Minecraft beats, off we go!

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: Minecraft Creator Playlist integration with album covers and search.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 4, 2026

Copy link
Copy Markdown

Greptile Summary

This PR integrates the Minecraft Creator-Safe Playlist API into the Resources Hub, adding browseable playback for 725 tracks organized by 70 albums with cover art, search, and a one-time changelog popup.

  • useMinecraftMusic hook fetches the playlist JSON, maps tracks to albums via a static albums.json, and pre-caches all audio blobs concurrently using the Cache API \u2014 but blob URLs created via URL.createObjectURL are never revoked, and pre-caching starts unconditionally for every ResourcesHub visitor regardless of whether they open Minecraft Music.
  • MinecraftMusicFilter provides an album sidebar with cover art thumbnails, graceful image fallback, and search; MinecraftChangelogPopup shows a one-time-dismissal dialog backed by localStorage.
  • Unstable index-based resource IDs (mc-music-${i}) mean the same track gets a different ID when filters or sort order change, silently breaking any favorite saved against that track.

Confidence Score: 3/5

The core feature works but has two memory/resource correctness issues and a data-integrity bug that affect all visitors to the Resources Hub, not just Minecraft Music users.

The hook unconditionally pre-caches 725 audio files on every ResourcesHub mount, leaks up to 725 blob URLs per mount cycle, and assigns unstable index-based IDs that silently break favoriting whenever filters or sort order change.

src/hooks/useMinecraftMusic.ts requires the most attention — the blob URL cleanup, the pre-cache guard, and the stable-ID fix all live there.

Important Files Changed

Filename Overview
src/hooks/useMinecraftMusic.ts New hook managing 725-track playlist; contains a blob URL memory leak, unstable index-based resource IDs that break favoriting, and unconditional aggressive pre-caching of all audio files on page load.
src/pages/ResourcesHub.tsx Connects Minecraft music hook and new UI components; search query syncing between community and Minecraft music views has a gap that can desync the visible search bar from the active filter.
src/components/resources/MinecraftMusicFilter.tsx New album sidebar filter with search, cover art thumbnails, and graceful fallback for missing images; well-structured.
src/components/resources/MinecraftChangelogPopup.tsx One-time-dismissal changelog dialog backed by localStorage; logic is correct and straightforward.
src/components/AudioPlayer.tsx Adds allowPlayBeforeReady prop for pre-cached audio; handles WaveSurfer lifecycle cleanly with isMounted guard.
src/types/resources.ts Added minecraft-music to the category union type; clean change.
src/utils/resourceCategories.tsx Added minecraft-music to icon and color lookup switches; straightforward.
public/data/albums.json New static track-to-album mapping for 70+ albums; data-only file, no code issues.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant RH as ResourcesHub (mount)
    participant Hook as useMinecraftMusic
    participant API as Playlist API
    participant LS as localStorage cache
    participant CA as Cache API (audio blobs)
    participant UI as MinecraftMusicFilter

    RH->>Hook: instantiate (unconditional)
    Hook->>LS: readCache(playlist)
    alt cache hit
        LS-->>Hook: PlaylistResponse
    else cache miss
        Hook->>API: GET /list
        API-->>Hook: 725 tracks
        Hook->>LS: writeCache(playlist)
    end
    Hook->>Hook: setData(PlaylistResponse)

    Note over Hook,CA: Pre-cache fires immediately with 6 concurrent workers
    loop for each of 725 MP3s
        Hook->>CA: cacheAudio(lfsUrl)
        CA-->>Hook: Blob
        Hook->>Hook: URL.createObjectURL(blob) never revoked
    end

    Hook->>UI: resources[], albums[], albumCounts
    UI-->>RH: album sidebar + track list
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant RH as ResourcesHub (mount)
    participant Hook as useMinecraftMusic
    participant API as Playlist API
    participant LS as localStorage cache
    participant CA as Cache API (audio blobs)
    participant UI as MinecraftMusicFilter

    RH->>Hook: instantiate (unconditional)
    Hook->>LS: readCache(playlist)
    alt cache hit
        LS-->>Hook: PlaylistResponse
    else cache miss
        Hook->>API: GET /list
        API-->>Hook: 725 tracks
        Hook->>LS: writeCache(playlist)
    end
    Hook->>Hook: setData(PlaylistResponse)

    Note over Hook,CA: Pre-cache fires immediately with 6 concurrent workers
    loop for each of 725 MP3s
        Hook->>CA: cacheAudio(lfsUrl)
        CA-->>Hook: Blob
        Hook->>Hook: URL.createObjectURL(blob) never revoked
    end

    Hook->>UI: resources[], albums[], albumCounts
    UI-->>RH: album sidebar + track list
Loading

Reviews (1): Last reviewed commit: "feat: Minecraft Creator Playlist integra..." | Re-trigger Greptile

Comment on lines +111 to +135
const processNext = async () => {
while (index < files.length) {
const i = index++;
const lfsUrl = resolveLfsUrl(files[i].url);
try {
const blob = await cacheAudio(lfsUrl);
if (blob) {
const blobUrl = URL.createObjectURL(blob);
urlMap[lfsUrl] = blobUrl;
if (i % 10 === 0 || i === files.length - 1) {
setCachedBlobUrls(prev => ({ ...prev, ...urlMap }));
}
}
} catch {
// skip individual file failures
}
}
if (Object.keys(urlMap).length > 0) {
setCachedBlobUrls(prev => ({ ...prev, ...urlMap }));
}
};

for (let i = 0; i < CONCURRENCY; i++) {
processNext();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Blob URL memory leak — 725 URLs never revoked

Every mount of useMinecraftMusic calls URL.createObjectURL(blob) for up to 725 tracks and stores the resulting URLs in state, but URL.revokeObjectURL() is never called — not on unmount, not when cachedBlobUrls is updated, not anywhere. Because preCacheStarted is a useRef (per-instance), each time ResourcesHub mounts a fresh batch of up to 725 object URLs is created and leaked. Over several navigation cycles the browser’s memory footprint grows unboundedly. The effect needs a cleanup path that calls URL.revokeObjectURL() on each stored blob URL when the component unmounts.

Comment on lines +174 to +190
})
.map((f, i) => {
const name = f.name.replace(/\.mp3$/i, '').trim();
const album = albumMap.get(name) || 'Other';
const parts = name.split(' - ', 2);
const title = parts.length > 1 ? parts[1].trim() : name;
const lfsUrl = resolveLfsUrl(f.url);
return {
id: `mc-music-${i}`,
title,
category: 'minecraft-music' as const,
subcategory: album,
filetype: 'mp3',
download_url: cachedBlobUrls[lfsUrl] || lfsUrl,
filename: f.name,
};
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Unstable resource IDs break favoriting

Resources are assigned id: \mc-music-${i}`whereiis the position in the filtered/sorted result array. The same track — e.g. "Cat" — will bemc-music-5in the "All Albums" view andmc-music-0after filtering to "Minecraft - Volume Alpha".ResourceCardcallsisFavorited(String(resource.id))andtoggleFavorite(String(resource.id))using this ID, so a track favorited in one filter state will silently appear un-favorited in any other filter state. Use a stable identifier such asf.name` as the resource ID instead of the loop index.

Comment thread src/hooks/useMinecraftMusic.ts Outdated
Comment on lines +103 to +136
useEffect(() => {
if (!data || preCacheStarted.current) return;
preCacheStarted.current = true;

const files = data.files.filter(f => f.name.endsWith('.mp3'));
const urlMap: Record<string, string> = {};
let index = 0;

const processNext = async () => {
while (index < files.length) {
const i = index++;
const lfsUrl = resolveLfsUrl(files[i].url);
try {
const blob = await cacheAudio(lfsUrl);
if (blob) {
const blobUrl = URL.createObjectURL(blob);
urlMap[lfsUrl] = blobUrl;
if (i % 10 === 0 || i === files.length - 1) {
setCachedBlobUrls(prev => ({ ...prev, ...urlMap }));
}
}
} catch {
// skip individual file failures
}
}
if (Object.keys(urlMap).length > 0) {
setCachedBlobUrls(prev => ({ ...prev, ...urlMap }));
}
};

for (let i = 0; i < CONCURRENCY; i++) {
processNext();
}
}, [data]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 All 725 tracks are pre-cached for every ResourcesHub visitor

useMinecraftMusic() is called unconditionally in ResourcesHub, and once data loads the pre-caching effect immediately starts fetching all 725 MP3 files from GitHub LFS with 6 concurrent workers — regardless of whether the user ever opens the Minecraft Music view. On a first visit this silently queues hundreds of megabytes of audio downloads in the background. The pre-cache should be deferred until the user first enters that view.

Comment on lines +174 to +186
const handleSearchWrapped = (e: React.ChangeEvent<HTMLInputElement>) => {
handleSearch(e);
if (isMinecraftMusicView) {
minecraftMusic.setSearchQuery(e.target.value);
}
};

const handleClearSearchWrapped = () => {
handleClearSearch();
if (isMinecraftMusicView) {
minecraftMusic.setSearchQuery('');
}
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Minecraft music search query can desync from the visible search bar

handleSearchWrapped only forwards keystrokes to minecraftMusic.setSearchQuery when isMinecraftMusicView is already true. Typing while in Community Music view then switching to Minecraft Music leaves minecraftMusic.searchQuery empty while the search bar shows text, so no filtering is applied. The clear handler has the same gap. Consider resetting minecraftMusic.searchQuery when musicView changes.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/components/AudioPlayer.tsx (1)

89-105: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Keep playPause()/setTime() gated on isReady.
allowPlayBeforeReady now enables the buttons before WaveSurfer fires ready, but these handlers still call into the instance as soon as the ref exists. Add an isReady guard (or keep the controls disabled) so togglePlay, skipForward, and skipBackward can’t run against an uninitialized waveform.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/AudioPlayer.tsx` around lines 89 - 105, Update the AudioPlayer
control handlers so WaveSurfer actions only run after initialization is
complete: `togglePlay`, `skipForward`, and `skipBackward` currently invoke
`wavesurfer.current.playPause()` and `wavesurfer.current.setTime()` as soon as
the ref exists, which bypasses the new early-enabled controls. Add an `isReady`
check inside these callbacks (or keep the buttons disabled until ready) so the
logic in `useCallback` for these handlers cannot execute against an unready
waveform instance.
src/components/resources/ResourceCard.tsx (1)

248-262: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Category badge can overflow for long minecraft-music album names.

The badge concatenates resource.category ("minecraft-music") with resource.subcategory (the album name, which can be lengthy, e.g. "Minecraft Legends: Laid Back Lutes (Remix)"). Neither the badge nor its inner span constrains width, so long album names will overflow or break the card layout — a visible regression specific to the new feature's primary browsing surface.

🎨 Proposed fix: constrain and truncate the badge
         <motion.div
-          className={`inline-flex items-center px-2 py-1 rounded-md text-xs ${getCategoryColor(resource.category)}`}
+          className={`inline-flex items-center px-2 py-1 rounded-md text-xs max-w-full ${getCategoryColor(resource.category)}`}
           whileHover={{ scale: 1.05 }}
         >
           {getCategoryIcon(resource.category)}
-          <span className="ml-1 capitalize">
+          <span className="ml-1 capitalize truncate max-w-[100px]">
             {resource.category === "minecraft-icons"
               ? "Mcicons"
               : resource.category}
           </span>
           {resource.subcategory && (
-            <span className="ml-1">({resource.subcategory})</span>
+            <span className="ml-1 truncate max-w-[140px]" title={resource.subcategory}>({resource.subcategory})</span>
           )}
         </motion.div>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/resources/ResourceCard.tsx` around lines 248 - 262, The
category badge in ResourceCard is allowing long minecraft-music subcategory text
to overflow and break the card layout. Update the badge rendering in
ResourceCard’s category/subcategory block to constrain its width and truncate or
ellipsize long text, especially the {resource.subcategory} portion, while
keeping the badge inline and readable. Use the existing getCategoryColor and
getCategoryIcon area as the place to apply the width/overflow handling so the
fix stays localized to the badge markup.
🧹 Nitpick comments (2)
src/components/AudioPlayer.tsx (1)

50-54: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor: simplify conditional.

♻️ Simplification
-    if (allowPlayBeforeReady) {
-      setIsLoading(false);
-    } else {
-      setIsLoading(true);
-    }
+    setIsLoading(!allowPlayBeforeReady);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/AudioPlayer.tsx` around lines 50 - 54, The loading-state
branch in AudioPlayer is a simple boolean toggle that can be simplified. Update
the allowPlayBeforeReady handling in the AudioPlayer component to set isLoading
directly from the condition instead of using an if/else, keeping the same
behavior while making the logic easier to read.
src/components/resources/MinecraftChangelogPopup.tsx (1)

67-86: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Rotated "X" icon doesn't read as an external-link indicator.

Rotating IconX 45° turns its diagonal cross into a "+"-like shape rather than an arrow, which is a confusing way to signal an external link. @tabler/icons-react (already a dependency) ships IconExternalLink for exactly this purpose.

✨ Proposed fix
-import { IconX, IconBrandSpotify, IconApi, IconMusic, IconAlbum, IconVinyl } from '`@tabler/icons-react`';
+import { IconX, IconExternalLink, IconBrandSpotify, IconApi, IconMusic, IconAlbum, IconVinyl } from '`@tabler/icons-react`';
...
                <IconBrandSpotify className="h-5 w-5" />
                Listen on Spotify
-                <IconX className="h-3 w-3 ml-auto rotate-45" />
+                <IconExternalLink className="h-3 w-3 ml-auto" />
...
                <IconApi className="h-4 w-4" />
                API Repository
-                <IconX className="h-3 w-3 ml-auto rotate-45" />
+                <IconExternalLink className="h-3 w-3 ml-auto" />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/resources/MinecraftChangelogPopup.tsx` around lines 67 - 86,
The external-link affordance in MinecraftChangelogPopup is using a rotated
IconX, which reads like a plus/cross instead of an outbound-link indicator.
Replace the rotated IconX in the Spotify and API Repository anchor buttons with
IconExternalLink from `@tabler/icons-react`, and keep the existing
sizing/alignment classes so the visual layout stays consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/AudioPlayer.tsx`:
- Around line 17-20: The minecraft-music card path is still using the default
ready-gated behavior in AudioPlayer. Update the `minecraft-music` branch in
`ResourceCard` to pass `allowPlayBeforeReady={true}` when rendering
`AudioPlayer`, so those tracks can start before the player is fully ready. Use
the `AudioPlayer` prop `allowPlayBeforeReady` and the `ResourceCard` branch that
selects the minecraft-music card to locate the change.

In `@src/hooks/useMinecraftMusic.ts`:
- Around line 103-136: The useEffect in useMinecraftMusic creates blob URLs via
URL.createObjectURL(blob) but never revokes them, causing a memory leak. Track
every created blob URL inside the pre-caching flow, add a cleanup function in
the effect to revoke all collected URLs with URL.revokeObjectURL, and make sure
any in-flight work in processNext is safely ignored after unmount so cached
tracks from cacheAudio do not keep accumulating memory.
- Around line 38-49: `fetchAndCachePlaylist` is caching unvalidated API data,
which can later break `albumData` and `resources` when `data.files` is not an
array. Update the `fetchAndCachePlaylist` flow in `useMinecraftMusic` to perform
a runtime shape check on the parsed `PlaylistResponse` (at minimum verify
`Array.isArray(data?.files)`) before calling `writeCache` or returning the data,
and treat invalid payloads as a failed fetch by logging and returning null.
- Around line 66-101: The Minecraft music hook currently runs its playlist load
and audio pre-cache on every ResourcesHub visit, even when the active view is
not Minecraft Music. Add an enabled flag to useMinecraftMusic and pass it from
ResourcesHub so the load and pre-cache effects only execute when Minecraft Music
is selected, while keeping ensurePlaylistCached separate if you still want to
warm the JSON cache.

In `@src/pages/ResourcesHub.tsx`:
- Around line 332-344: Update the Minecraft Music branch in ResourcesHub so it
uses the shared search state instead of hardcoding isSearching=false, and wire
the empty-state messaging to minecraftMusic.searchQuery so zero-result searches
show the correct “No resources match your search” behavior. Also make
onClearFilters clear both the Minecraft hook search state and the top-level
searchQuery from useResources(), so the visible input and the filtered results
stay in sync when clearing filters.

---

Outside diff comments:
In `@src/components/AudioPlayer.tsx`:
- Around line 89-105: Update the AudioPlayer control handlers so WaveSurfer
actions only run after initialization is complete: `togglePlay`, `skipForward`,
and `skipBackward` currently invoke `wavesurfer.current.playPause()` and
`wavesurfer.current.setTime()` as soon as the ref exists, which bypasses the new
early-enabled controls. Add an `isReady` check inside these callbacks (or keep
the buttons disabled until ready) so the logic in `useCallback` for these
handlers cannot execute against an unready waveform instance.

In `@src/components/resources/ResourceCard.tsx`:
- Around line 248-262: The category badge in ResourceCard is allowing long
minecraft-music subcategory text to overflow and break the card layout. Update
the badge rendering in ResourceCard’s category/subcategory block to constrain
its width and truncate or ellipsize long text, especially the
{resource.subcategory} portion, while keeping the badge inline and readable. Use
the existing getCategoryColor and getCategoryIcon area as the place to apply the
width/overflow handling so the fix stays localized to the badge markup.

---

Nitpick comments:
In `@src/components/AudioPlayer.tsx`:
- Around line 50-54: The loading-state branch in AudioPlayer is a simple boolean
toggle that can be simplified. Update the allowPlayBeforeReady handling in the
AudioPlayer component to set isLoading directly from the condition instead of
using an if/else, keeping the same behavior while making the logic easier to
read.

In `@src/components/resources/MinecraftChangelogPopup.tsx`:
- Around line 67-86: The external-link affordance in MinecraftChangelogPopup is
using a rotated IconX, which reads like a plus/cross instead of an outbound-link
indicator. Replace the rotated IconX in the Spotify and API Repository anchor
buttons with IconExternalLink from `@tabler/icons-react`, and keep the existing
sizing/alignment classes so the visual layout stays consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c1699872-5e78-4517-8a54-1caae50bdbc8

📥 Commits

Reviewing files that changed from the base of the PR and between 2525624 and bf51f33.

⛔ Files ignored due to path filters (70)
  • public/albums/Axolotl.jpg is excluded by !**/*.jpg
  • public/albums/Caller's Bane (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Dragon Fish.jpg is excluded by !**/*.jpg
  • public/albums/Happy Ghast Song (Minecraft Live Version).jpg is excluded by !**/*.jpg
  • public/albums/Happy Ghast Song.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft - Volume Alpha.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft - Volume Beta.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Dungeons (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Dungeons_ Creeping Winter (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Dungeons_ Echoing Void (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Dungeons_ Flames of the Nether (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Dungeons_ Hidden Depths (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Dungeons_ Howling Peaks (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Dungeons_ Jungle Awakens (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Dungeons_ Seasonal Adventures (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Dungeons_ Tranquil Beats (Lo-Fi Remix).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Dungeons_ Ultimate Additions (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Earth (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Education_ Frozen Planet II (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Education_ Planet Earth III (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Legends (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Legends_ A Legend Begins (Original Score).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Legends_ Fiery Foes (Original Score).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Legends_ Laid Back Lutes (Remix).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Legends_ Unite the Overworld! (Original Score).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Live_ 2023 (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Live_ 2024 (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Live_ March 2025 (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Live_ March 2026 (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Live_ September 2025 (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Soothing Scenes_ Dreamy Desert.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Soothing Scenes_ Glowing Cave.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Soothing Scenes_ Relaxing Aquarium.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Soothing Scenes_ Relaxing Beach Escape.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Soothing Scenes_ Relaxing Cherry Grove.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Soothing Scenes_ Relaxing Falling Snow.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Soothing Scenes_ Relaxing Fireplace.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Soothing Scenes_ Relaxing Rainy Swamp.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Soothing Scenes_ Serene Snow.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft Soothing Scenes_ Soothing Story.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Battle & Tumble (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Caves & Cliffs (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Chaos Cubed (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Chase the Skies (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Chinese Mythology (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Dungeons & Dragons (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Egyptian Mythology (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Glide Mini Game (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Greek Mythology (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Hello Kitty and Friends (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Lava Chicken (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Nether Update (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Norse Mythology (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Pixel Drift.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Pixel Genesis.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Retro Arcade Action (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Shape Your World.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Soothing Farm Morning.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Soothing Synths (Monolism Remix).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Spring to Life.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Tetris (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ The Copper Age (Original Trailer Score).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ The Garden Awakens.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ The Wild Update (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Trails & Tales (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Tricky Trials (Original Game Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Triple Bundle.jpg is excluded by !**/*.jpg
  • public/albums/Minecraft_ Whimsical Compilation (Original Soundtrack).jpg is excluded by !**/*.jpg
  • public/albums/Pigstep (Just Dance Version).jpg is excluded by !**/*.jpg
  • public/albums/Shuniji.jpg is excluded by !**/*.jpg
📒 Files selected for processing (12)
  • public/cover.webp
  • public/data/albums.json
  • src/components/AudioPlayer.tsx
  • src/components/Footer.tsx
  • src/components/Navbar.tsx
  • src/components/resources/MinecraftChangelogPopup.tsx
  • src/components/resources/MinecraftMusicFilter.tsx
  • src/components/resources/ResourceCard.tsx
  • src/hooks/useMinecraftMusic.ts
  • src/pages/ResourcesHub.tsx
  • src/types/resources.ts
  • src/utils/resourceCategories.tsx
💤 Files with no reviewable changes (1)
  • src/components/Navbar.tsx

Comment thread src/components/AudioPlayer.tsx
Comment thread src/hooks/useMinecraftMusic.ts
Comment thread src/hooks/useMinecraftMusic.ts Outdated
Comment thread src/hooks/useMinecraftMusic.ts Outdated
Comment thread src/pages/ResourcesHub.tsx Outdated
Comment thread src/pages/ResourcesHub.tsx
@creatorcluster
creatorcluster merged commit a2893e1 into creatorcluster:main Jul 4, 2026
1 of 3 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