feat: Minecraft Creator Playlist integration with album covers, searc… - #58
Conversation
…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
|
@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. |
|
Warning Review limit reached
Next review available in: 42 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThis PR adds a Minecraft-specific music mode to the Resources Hub, backed by a new album dataset and a ChangesMinecraft Music Feature
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
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Greptile SummaryThis 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.
Confidence Score: 3/5The 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.
|
| 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
%%{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
Reviews (1): Last reviewed commit: "feat: Minecraft Creator Playlist integra..." | Re-trigger Greptile
| 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(); | ||
| } |
There was a problem hiding this comment.
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.
| }) | ||
| .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, | ||
| }; | ||
| }); |
There was a problem hiding this comment.
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.
| 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]); |
There was a problem hiding this comment.
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.
| const handleSearchWrapped = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
| handleSearch(e); | ||
| if (isMinecraftMusicView) { | ||
| minecraftMusic.setSearchQuery(e.target.value); | ||
| } | ||
| }; | ||
|
|
||
| const handleClearSearchWrapped = () => { | ||
| handleClearSearch(); | ||
| if (isMinecraftMusicView) { | ||
| minecraftMusic.setSearchQuery(''); | ||
| } | ||
| }; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 winKeep
playPause()/setTime()gated onisReady.
allowPlayBeforeReadynow enables the buttons before WaveSurfer firesready, but these handlers still call into the instance as soon as the ref exists. Add anisReadyguard (or keep the controls disabled) sotogglePlay,skipForward, andskipBackwardcan’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 winCategory badge can overflow for long minecraft-music album names.
The badge concatenates
resource.category("minecraft-music") withresource.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 valueMinor: 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 winRotated "X" icon doesn't read as an external-link indicator.
Rotating
IconX45° 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) shipsIconExternalLinkfor 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
⛔ Files ignored due to path filters (70)
public/albums/Axolotl.jpgis excluded by!**/*.jpgpublic/albums/Caller's Bane (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Dragon Fish.jpgis excluded by!**/*.jpgpublic/albums/Happy Ghast Song (Minecraft Live Version).jpgis excluded by!**/*.jpgpublic/albums/Happy Ghast Song.jpgis excluded by!**/*.jpgpublic/albums/Minecraft - Volume Alpha.jpgis excluded by!**/*.jpgpublic/albums/Minecraft - Volume Beta.jpgis excluded by!**/*.jpgpublic/albums/Minecraft Dungeons (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Dungeons_ Creeping Winter (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Dungeons_ Echoing Void (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Dungeons_ Flames of the Nether (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Dungeons_ Hidden Depths (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Dungeons_ Howling Peaks (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Dungeons_ Jungle Awakens (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Dungeons_ Seasonal Adventures (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Dungeons_ Tranquil Beats (Lo-Fi Remix).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Dungeons_ Ultimate Additions (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Earth (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Education_ Frozen Planet II (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Education_ Planet Earth III (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Legends (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Legends_ A Legend Begins (Original Score).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Legends_ Fiery Foes (Original Score).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Legends_ Laid Back Lutes (Remix).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Legends_ Unite the Overworld! (Original Score).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Live_ 2023 (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Live_ 2024 (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Live_ March 2025 (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Live_ March 2026 (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Live_ September 2025 (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft Soothing Scenes_ Dreamy Desert.jpgis excluded by!**/*.jpgpublic/albums/Minecraft Soothing Scenes_ Glowing Cave.jpgis excluded by!**/*.jpgpublic/albums/Minecraft Soothing Scenes_ Relaxing Aquarium.jpgis excluded by!**/*.jpgpublic/albums/Minecraft Soothing Scenes_ Relaxing Beach Escape.jpgis excluded by!**/*.jpgpublic/albums/Minecraft Soothing Scenes_ Relaxing Cherry Grove.jpgis excluded by!**/*.jpgpublic/albums/Minecraft Soothing Scenes_ Relaxing Falling Snow.jpgis excluded by!**/*.jpgpublic/albums/Minecraft Soothing Scenes_ Relaxing Fireplace.jpgis excluded by!**/*.jpgpublic/albums/Minecraft Soothing Scenes_ Relaxing Rainy Swamp.jpgis excluded by!**/*.jpgpublic/albums/Minecraft Soothing Scenes_ Serene Snow.jpgis excluded by!**/*.jpgpublic/albums/Minecraft Soothing Scenes_ Soothing Story.jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Battle & Tumble (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Caves & Cliffs (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Chaos Cubed (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Chase the Skies (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Chinese Mythology (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Dungeons & Dragons (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Egyptian Mythology (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Glide Mini Game (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Greek Mythology (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Hello Kitty and Friends (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Lava Chicken (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Nether Update (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Norse Mythology (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Pixel Drift.jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Pixel Genesis.jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Retro Arcade Action (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Shape Your World.jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Soothing Farm Morning.jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Soothing Synths (Monolism Remix).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Spring to Life.jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Tetris (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ The Copper Age (Original Trailer Score).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ The Garden Awakens.jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ The Wild Update (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Trails & Tales (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Tricky Trials (Original Game Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Triple Bundle.jpgis excluded by!**/*.jpgpublic/albums/Minecraft_ Whimsical Compilation (Original Soundtrack).jpgis excluded by!**/*.jpgpublic/albums/Pigstep (Just Dance Version).jpgis excluded by!**/*.jpgpublic/albums/Shuniji.jpgis excluded by!**/*.jpg
📒 Files selected for processing (12)
public/cover.webppublic/data/albums.jsonsrc/components/AudioPlayer.tsxsrc/components/Footer.tsxsrc/components/Navbar.tsxsrc/components/resources/MinecraftChangelogPopup.tsxsrc/components/resources/MinecraftMusicFilter.tsxsrc/components/resources/ResourceCard.tsxsrc/hooks/useMinecraftMusic.tssrc/pages/ResourcesHub.tsxsrc/types/resources.tssrc/utils/resourceCategories.tsx
💤 Files with no reviewable changes (1)
- src/components/Navbar.tsx
…I validation, allowPlayBeforeReady
…h, and changelog popup
Summary by CodeRabbit
New Features
Bug Fixes