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));
}