diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..783d1c6 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,39 @@ +# Development Guide + +## Prerequisites + +Before running the application locally, ensure you have the following installed: + +1. **Go** (v1.23+ recommended) +2. **Node.js** (v16+ recommended) +3. **Wails CLI** + +### Installing Wails + +Since you already have Go installed, you can install the Wails CLI by running: + +```bash +go install github.com/wailsapp/wails/v2/cmd/wails@latest +``` + +Ensure that your `go/bin` directory is in your PATH. You can check if it's installed by running `wails version`. + +## Running the Application + +To run the application in development mode (with hot reloading for both frontend and backend): + +```bash +wails dev +``` + +This will compiles the application and open it in a window. It also starts a browser-based version at http://localhost:34115. + +## Building for Production + +To create a production build (Application.app): + +```bash +wails build +``` + +The output will be in the `build/bin` directory. diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 6174a3a..7210b0b 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -357,14 +357,14 @@ function App() { onToggleSelectAll={toggleSelectAll} onDownloadTrack={download.handleDownloadTrack} onDownloadLyrics={(spotifyId, name, artists, albumName, _folderName, _isArtistDiscography, position, albumArtist, releaseDate, discNumber) => - lyrics.handleDownloadLyrics(spotifyId, name, artists, albumName, album_info.name, position, albumArtist, releaseDate, discNumber) + lyrics.handleDownloadLyrics(spotifyId, name, artists, albumName, album_info.name, position, albumArtist, releaseDate, discNumber, true) } onDownloadCover={(coverUrl, trackName, artistName, albumName, _folderName, _isArtistDiscography, position, trackId, albumArtist, releaseDate, discNumber) => - cover.handleDownloadCover(coverUrl, trackName, artistName, albumName, album_info.name, position, trackId, albumArtist, releaseDate, discNumber) + cover.handleDownloadCover(coverUrl, trackName, artistName, albumName, album_info.name, position, trackId, albumArtist, releaseDate, discNumber, true) } onCheckAvailability={availability.checkAvailability} - onDownloadAllLyrics={() => lyrics.handleDownloadAllLyrics(track_list, album_info.name)} - onDownloadAllCovers={() => cover.handleDownloadAllCovers(track_list, album_info.name)} + onDownloadAllLyrics={() => lyrics.handleDownloadAllLyrics(track_list, album_info.name, undefined, true)} + onDownloadAllCovers={() => cover.handleDownloadAllCovers(track_list, album_info.name, true)} onDownloadAll={() => download.handleDownloadAll(track_list, undefined, true)} onDownloadSelected={() => download.handleDownloadSelected(selectedTracks, track_list, undefined, true) @@ -684,7 +684,7 @@ function App() {
- + {/* Main content area with sidebar offset */}
diff --git a/frontend/src/hooks/useCover.ts b/frontend/src/hooks/useCover.ts index 174fef9..93fa12f 100644 --- a/frontend/src/hooks/useCover.ts +++ b/frontend/src/hooks/useCover.ts @@ -26,7 +26,8 @@ export function useCover() { trackId?: string, albumArtist?: string, releaseDate?: string, - discNumber?: number + discNumber?: number, + isAlbum?: boolean ) => { if (!coverUrl) { toast.error("No cover URL found for this track"); @@ -54,7 +55,8 @@ export function useCover() { }; // For playlist/discography, prepend the folder name - if (playlistName) { + // Only do this if it's NOT an album download, to avoid double nesting (AlbumName/Artist/AlbumName) + if (playlistName && !isAlbum) { outputDir = joinPath(os, outputDir, sanitizePath(playlistName.replace(/\//g, " "), os)); } @@ -113,7 +115,8 @@ export function useCover() { const handleDownloadAllCovers = async ( tracks: TrackMetadata[], - playlistName?: string + playlistName?: string, + isAlbum?: boolean // Add isAlbum parameter ) => { if (tracks.length === 0) { toast.error("No tracks to download covers"); @@ -166,7 +169,8 @@ export function useCover() { }; // For playlist/discography, prepend the folder name - if (playlistName) { + // Only do this if it's NOT an album download + if (playlistName && !isAlbum) { outputDir = joinPath(os, outputDir, sanitizePath(playlistName.replace(/\//g, " "), os)); } diff --git a/frontend/src/hooks/useLyrics.ts b/frontend/src/hooks/useLyrics.ts index c5f786a..b0f5a18 100644 --- a/frontend/src/hooks/useLyrics.ts +++ b/frontend/src/hooks/useLyrics.ts @@ -24,7 +24,8 @@ export function useLyrics() { position?: number, albumArtist?: string, releaseDate?: string, - discNumber?: number + discNumber?: number, + isAlbum?: boolean // Add isAlbum parameter ) => { if (!spotifyId) { toast.error("No Spotify ID found for this track"); @@ -51,7 +52,8 @@ export function useLyrics() { }; // For playlist/discography, prepend the folder name - if (playlistName) { + // Only do this if it's NOT an album download + if (playlistName && !isAlbum) { outputDir = joinPath(os, outputDir, sanitizePath(playlistName.replace(/\//g, " "), os)); } @@ -113,7 +115,8 @@ export function useLyrics() { const handleDownloadAllLyrics = async ( tracks: TrackMetadata[], playlistName?: string, - _isArtistDiscography?: boolean + _isArtistDiscography?: boolean, + isAlbum?: boolean // Add isAlbum parameter ) => { const tracksWithSpotifyId = tracks.filter((track) => track.spotify_id); @@ -150,12 +153,12 @@ export function useLyrics() { // Replace forward slashes in template data values to prevent them from being interpreted as path separators const placeholder = "__SLASH_PLACEHOLDER__"; - + // Determine if we should use album track number or sequential position const useAlbumTrackNumber = settings.folderTemplate?.includes("{album}") || false; // Use track.track_number for album context, otherwise use sequential position (consistent with track download) const trackPosition = useAlbumTrackNumber ? (track.track_number || i + 1) : (i + 1); - + // Build output path using template system const templateData: TemplateData = { artist: track.artists?.replace(/\//g, placeholder), @@ -166,7 +169,8 @@ export function useLyrics() { }; // For playlist/discography, prepend the folder name - if (playlistName) { + // Only do this if it's NOT an album download + if (playlistName && !isAlbum) { outputDir = joinPath(os, outputDir, sanitizePath(playlistName.replace(/\//g, " "), os)); }